update sdl Merge commit '644725478f4de0f074a6834e8423ac36dce3974f'

This commit is contained in:
2023-09-23 18:53:11 +02:00
172 changed files with 7495 additions and 4062 deletions

View File

@ -230,7 +230,31 @@ elseif(HAVE_X11)
target_link_libraries(testnative PRIVATE X11)
endif()
set(gamepad_images
find_package(Python3)
function(files2headers OUTPUT)
set(xxd "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/xxd.py")
set(inputs ${ARGN})
set(outputs )
foreach(input IN LISTS inputs)
get_filename_component(file_we "${input}" NAME_WE)
set(intermediate "${CMAKE_CURRENT_BINARY_DIR}/${file_we}.h")
set(output "${CMAKE_CURRENT_SOURCE_DIR}/${file_we}.h")
list(APPEND outputs "${output}")
if(Python3_FOUND AND Python3_VERSION VERSION_GREATER_EQUAL "3.2")
list(APPEND outputs "${intermediate}")
# Don't add the 'output' header to the output, to avoid marking them as GENERATED
# (generated files are removed when running the CLEAN target)
add_custom_command(OUTPUT "${intermediate}"
COMMAND Python3::Interpreter "${xxd}" -i "${CMAKE_CURRENT_SOURCE_DIR}/${input}" "-o" "${intermediate}"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${intermediate}" "${output}"
DEPENDS "${xxd}" "${bmp}"
)
endif()
endforeach()
set(${OUTPUT} "${outputs}" PARENT_SCOPE)
endfunction()
files2headers(gamepad_image_headers
gamepad_axis_arrow.bmp
gamepad_axis.bmp
gamepad_back.bmp
@ -249,24 +273,7 @@ set(gamepad_images
gamepad_front.bmp
gamepad_touchpad.bmp
)
set(gamepad_image_headers)
find_package(Python3)
if(Python3_FOUND AND Python3_VERSION VERSION_GREATER_EQUAL "3.2")
set(xxd "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/xxd.py")
foreach(bmp ${gamepad_images})
get_filename_component(bmp_we "${bmp}" NAME_WE)
set(intermediate "${CMAKE_CURRENT_BINARY_DIR}/${bmp_we}.h")
set(final "${CMAKE_CURRENT_SOURCE_DIR}/${bmp_we}.h")
# Don't add the 'final' headers to the output, to avoid marking them as GENERATED
# (generated files are removed when running the CLEAN target)
add_custom_command(OUTPUT "${intermediate}"
COMMAND Python3::Interpreter "${xxd}" -i "${CMAKE_CURRENT_SOURCE_DIR}/${bmp}" "-o" "${intermediate}"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${intermediate}" "${final}"
DEPENDS "${xxd}" "${bmp}"
)
list(APPEND gamepad_image_headers "${intermediate}" "${final}")
endforeach()
endif()
files2headers(icon_bmp_header icon.bmp)
add_sdl_test_executable(testaudio NEEDS_RESOURCES TESTUTILS SOURCES testaudio.c)
add_sdl_test_executable(testfile NONINTERACTIVE SOURCES testfile.c)
@ -296,6 +303,9 @@ add_sdl_test_executable(testoverlay NEEDS_RESOURCES TESTUTILS SOURCES testoverla
add_sdl_test_executable(testplatform NONINTERACTIVE SOURCES testplatform.c)
add_sdl_test_executable(testpower NONINTERACTIVE SOURCES testpower.c)
add_sdl_test_executable(testfilesystem NONINTERACTIVE SOURCES testfilesystem.c)
if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
add_sdl_test_executable(testfilesystem_pre SOURCES testfilesystem_pre.c NONINTERACTIVE NONINTERACTIVE_TIMEOUT 60)
endif()
add_sdl_test_executable(testrendertarget NEEDS_RESOURCES TESTUTILS SOURCES testrendertarget.c)
add_sdl_test_executable(testscale NEEDS_RESOURCES TESTUTILS SOURCES testscale.c)
add_sdl_test_executable(testsem NONINTERACTIVE NONINTERACTIVE_ARGS 10 NONINTERACTIVE_TIMEOUT 30 SOURCES testsem.c)
@ -303,7 +313,7 @@ add_sdl_test_executable(testsensor SOURCES testsensor.c)
add_sdl_test_executable(testshader NEEDS_RESOURCES TESTUTILS SOURCES testshader.c)
add_sdl_test_executable(testshape NEEDS_RESOURCES SOURCES testshape.c)
add_sdl_test_executable(testsprite NEEDS_RESOURCES TESTUTILS SOURCES testsprite.c)
add_sdl_test_executable(testspriteminimal NEEDS_RESOURCES TESTUTILS SOURCES testspriteminimal.c)
add_sdl_test_executable(testspriteminimal SOURCES testspriteminimal.c ${icon_bmp_header})
add_sdl_test_executable(teststreaming NEEDS_RESOURCES TESTUTILS SOURCES teststreaming.c)
add_sdl_test_executable(testtimer NONINTERACTIVE NONINTERACTIVE_TIMEOUT 60 SOURCES testtimer.c)
add_sdl_test_executable(testurl SOURCES testurl.c)
@ -504,6 +514,10 @@ foreach(TEST ${SDL_TEST_EXECUTABLES})
endif()
endforeach()
if(TARGET testfilesystem_pre)
set_property(TEST testfilesystem APPEND PROPERTY DEPENDS testfilesystem_pre)
endif()
if(SDL_INSTALL_TESTS)
if(RISCOS)
install(

View File

@ -15,8 +15,6 @@
pump the event loop and catch keystrokes.
*/
#include <stdlib.h>
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#endif
@ -25,22 +23,10 @@
#include <SDL3/SDL_main.h>
#include <SDL3/SDL_test.h>
static SDL_Window *window;
static SDL_Renderer *renderer;
static SDLTest_CommonState *state;
static SDLTest_TextWindow *textwin;
static int done;
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void
quit(int rc)
{
SDL_Quit();
/* Let 'main()' return normally */
if (rc != 0) {
exit(rc);
}
}
static void
print_string(char **text, size_t *maxlen, const char *fmt, ...)
{
@ -171,6 +157,7 @@ PrintText(const char *eventtype, const char *text)
static void loop(void)
{
SDL_Event event;
int i;
/* Check for events */
/*SDL_WaitEvent(&event); emscripten does not like waiting*/
@ -234,11 +221,13 @@ static void loop(void)
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDLTest_TextWindowDisplay(textwin, renderer);
SDL_RenderPresent(renderer);
for (i = 0; i < state->num_windows; i++) {
SDL_SetRenderDrawColor(state->renderers[i], 0, 0, 0, 255);
SDL_RenderClear(state->renderers[i]);
SDL_SetRenderDrawColor(state->renderers[i], 255, 255, 255, 255);
SDLTest_TextWindowDisplay(textwin, state->renderers[i]);
SDL_RenderPresent(state->renderers[i]);
}
/* Slow down framerate */
SDL_Delay(100);
@ -252,13 +241,14 @@ static void loop(void)
int main(int argc, char *argv[])
{
SDLTest_CommonState *state;
int w, h;
/* Initialize test framework */
state = SDLTest_CommonCreateState(argv, 0);
state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
if (state == NULL) {
return 1;
}
state->window_title = "CheckKeys Test";
/* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
@ -275,31 +265,22 @@ int main(int argc, char *argv[])
SDL_SetHint(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, "1");
/* Initialize SDL */
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
if (!SDLTest_CommonInit(state)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
return 1;
}
/* Set 640x480 video mode */
window = SDL_CreateWindow("CheckKeys Test", 640, 480, 0);
if (window == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create 640x480 window: %s\n",
SDL_GetError());
quit(2);
}
renderer = SDL_CreateRenderer(window, NULL, 0);
if (renderer == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n",
SDL_GetError());
quit(2);
}
textwin = SDLTest_TextWindowCreate(0, 0, 640, 480);
SDL_GetWindowSize(state->windows[0], &w, &h);
textwin = SDLTest_TextWindowCreate(0.f, 0.f, (float)w, (float)h);
#ifdef __IOS__
/* Creating the context creates the view, which we need to show keyboard */
SDL_GL_CreateContext(window);
{
int i;
/* Creating the context creates the view, which we need to show keyboard */
for (i = 0; i < state->num_windows; i++) {
SDL_GL_CreateContext(state->windows[i]);
}
}
#endif
SDL_StartTextInput();
@ -319,7 +300,8 @@ int main(int argc, char *argv[])
}
#endif
SDL_Quit();
SDLTest_CommonDestroyState(state);
SDLTest_TextWindowDestroy(textwin);
SDLTest_CleanupTextDrawing();
SDLTest_CommonQuit(state);
return 0;
}

View File

@ -303,6 +303,9 @@ int main(int argc, char *argv[])
}
#endif
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_WaitThread(thread, NULL);
SDL_Quit();
SDLTest_CommonDestroyState(state);

View File

@ -3,13 +3,15 @@
# Based on http/server.py from Python
from argparse import ArgumentParser
import contextlib
from http.server import SimpleHTTPRequestHandler
from http.server import ThreadingHTTPServer
import socket
from socketserver import TCPServer
def serve_forever(port: int, ServerClass):
handler = SimpleHTTPRequestHandler
handler.extensions_map = {
class MyHTTPRequestHandler(SimpleHTTPRequestHandler):
extensions_map = {
".manifest": "text/cache-manifest",
".html": "text/html",
".png": "image/png",
@ -21,14 +23,25 @@ def serve_forever(port: int, ServerClass):
"": "application/octet-stream",
}
def end_headers(self):
self.send_my_headers()
SimpleHTTPRequestHandler.end_headers(self)
def send_my_headers(self):
self.send_header("Cache-Control", "no-cache, no-store, must-revalidate")
self.send_header("Pragma", "no-cache")
self.send_header("Expires", "0")
def serve_forever(port: int, ServerClass):
handler = MyHTTPRequestHandler
addr = ("0.0.0.0", port)
HandlerClass = SimpleHTTPRequestHandler
with ServerClass(addr, handler) as httpd:
host, port = httpd.socket.getsockname()[:2]
url_host = f"[{host}]" if ":" in host else host
print(
f"Serving HTTP on {host} port {port} (http://{url_host}:{port}/) ..."
)
print(f"Serving HTTP on {host} port {port} (http://{url_host}:{port}/) ...")
try:
httpd.serve_forever()
except KeyboardInterrupt:
@ -42,16 +55,11 @@ def main():
parser.add_argument("-d", dest="directory", type=str, default=None)
args = parser.parse_args()
import contextlib
import http.server
import socket
class DualStackServer(http.server.ThreadingHTTPServer):
class DualStackServer(ThreadingHTTPServer):
def server_bind(self):
# suppress exception when protocol is IPv4
with contextlib.suppress(Exception):
self.socket.setsockopt(
socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
return super().server_bind()
def finish_request(self, request, client_address):

52
external/sdl/SDL/test/icon.h vendored Normal file
View File

@ -0,0 +1,52 @@
unsigned char icon_bmp[] = {
0x42, 0x4d, 0x42, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00,
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00,
0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x6d, 0x0b, 0x00, 0x00, 0x6d, 0x0b, 0x00, 0x00, 0x03, 0x00,
0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x22, 0x22, 0x22,
0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22,
0x21, 0x11, 0x11, 0x12, 0x22, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x12, 0x21, 0x11, 0x11, 0x11, 0x11, 0x12, 0x21, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x22, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x21, 0x11,
0x22, 0x22, 0x22, 0x22, 0x11, 0x12, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x12, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x22, 0x22,
0x22, 0x21, 0x12, 0x22, 0x22, 0x22, 0x22, 0x10, 0x00, 0x00, 0x00, 0x00,
0x01, 0x22, 0x22, 0x22, 0x22, 0x21, 0x12, 0x22, 0x22, 0x22, 0x22, 0x10,
0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x10, 0x00, 0x00, 0x00, 0x00,
0x01, 0x22, 0x22, 0x11, 0x11, 0x22, 0x22, 0x11, 0x11, 0x22, 0x22, 0x10,
0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x22, 0x11, 0x01, 0x22, 0x22, 0x11,
0x01, 0x22, 0x22, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x22, 0x11,
0x11, 0x22, 0x22, 0x11, 0x11, 0x22, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x12, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x22, 0x22, 0x22,
0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
unsigned int icon_bmp_len = 578;

View File

@ -31,15 +31,14 @@ static struct
SDL_AudioSpec spec;
Uint8 *sound; /* Pointer to wave data */
Uint32 soundlen; /* Length of wave data */
Uint32 soundpos;
} wave;
static SDL_AudioDeviceID device;
static SDL_AudioStream *stream;
static void fillerup(void)
{
if (SDL_GetAudioStreamAvailable(stream) < (int) ((wave.soundlen / 2))) {
const int minimum = (wave.soundlen / SDL_AUDIO_FRAMESIZE(wave.spec)) / 2;
if (SDL_GetAudioStreamQueued(stream) < minimum) {
SDL_PutAudioStreamData(stream, wave.sound, wave.soundlen);
}
}
@ -58,30 +57,22 @@ quit(int rc)
static void
close_audio(void)
{
if (device != 0) {
if (stream) {
SDL_DestroyAudioStream(stream);
stream = NULL;
SDL_CloseAudioDevice(device);
device = 0;
}
}
static void
open_audio(void)
{
device = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &wave.spec);
if (!device) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open audio: %s\n", SDL_GetError());
SDL_free(wave.sound);
quit(2);
}
stream = SDL_CreateAndBindAudioStream(device, &wave.spec);
stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &wave.spec, NULL, NULL);
if (!stream) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create audio stream: %s\n", SDL_GetError());
SDL_CloseAudioDevice(device);
SDL_free(wave.sound);
quit(2);
}
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream));
}

View File

@ -10,6 +10,8 @@
#include "testutils.h"
#define POOF_LIFETIME 250
#define VISUALIZER_WIDTH 100
#define VISUALIZER_HEIGHT 50
typedef struct Texture
{
@ -50,6 +52,15 @@ struct Thing
SDL_bool iscapture;
SDL_AudioSpec spec;
Thing *physdev;
SDL_bool visualizer_enabled;
SDL_bool visualizer_updated;
SDL_Texture *visualizer;
SDL_Mutex *postmix_lock;
float *postmix_buffer;
int postmix_buflen;
int postmix_allocated;
SDL_AudioSpec postmix_spec;
SDL_AtomicInt postmix_updated;
} logdev;
struct {
SDL_AudioSpec spec;
@ -98,6 +109,7 @@ static SDLTest_CommonState *state = NULL;
static Thing *things = NULL;
static char *current_titlebar = NULL;
static Thing *mouseover_thing = NULL;
static Thing *droppable_highlighted_thing = NULL;
static Thing *dragging_thing = NULL;
static int dragging_button = -1;
@ -110,10 +122,16 @@ static Texture *soundboard_texture = NULL;
static Texture *soundboard_levels_texture = NULL;
static void DestroyTexture(Texture *tex);
static void DestroyThing(Thing *thing);
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void Quit(int rc)
{
while (things != NULL) {
DestroyThing(things); /* make sure all the audio devices are closed, etc. */
}
DestroyTexture(physdev_texture);
DestroyTexture(logdev_texture);
DestroyTexture(audio_texture);
@ -121,6 +139,7 @@ static void Quit(int rc)
DestroyTexture(soundboard_texture);
DestroyTexture(soundboard_levels_texture);
SDLTest_CommonQuit(state);
/* Let 'main()' return normally */
if (rc != 0) {
exit(rc);
@ -193,6 +212,8 @@ static Thing *UpdateMouseOver(const float x, const float y)
thing = FindThingAtPoint(x, y);
}
mouseover_thing = thing;
if (!thing) {
SetDefaultTitleBar();
} else if (thing->titlebar) {
@ -202,7 +223,7 @@ static Thing *UpdateMouseOver(const float x, const float y)
return thing;
}
static Thing *CreateThing(ThingType what, float x, float y, float z, float w, float h, Texture *texture, char *titlebar)
static Thing *CreateThing(ThingType what, float x, float y, float z, float w, float h, Texture *texture, const char *titlebar)
{
Thing *last = NULL;
Thing *i;
@ -232,7 +253,7 @@ static Thing *CreateThing(ThingType what, float x, float y, float z, float w, fl
thing->scale = 1.0f;
thing->createticks = SDL_GetTicks();
thing->texture = texture;
thing->titlebar = titlebar;
thing->titlebar = titlebar ? xstrdup(titlebar) : NULL;
/* insert in list by Z order (furthest from the "camera" first, so they get drawn over; negative Z is not drawn at all). */
if (things == NULL) {
@ -272,21 +293,40 @@ static void DestroyThing(Thing *thing)
return;
}
if (mouseover_thing == thing) {
mouseover_thing = NULL;
}
if (droppable_highlighted_thing == thing) {
droppable_highlighted_thing = NULL;
}
if (dragging_thing == thing) {
dragging_thing = NULL;
}
switch (thing->what) {
case THING_POOF: break;
case THING_NULL: break;
case THING_TRASHCAN: break;
case THING_LOGDEV:
case THING_LOGDEV_CAPTURE:
SDL_CloseAudioDevice(thing->data.logdev.devid);
SDL_DestroyTexture(thing->data.logdev.visualizer);
SDL_DestroyMutex(thing->data.logdev.postmix_lock);
SDL_free(thing->data.logdev.postmix_buffer);
break;
case THING_PHYSDEV:
case THING_PHYSDEV_CAPTURE:
SDL_free(thing->data.physdev.name);
break;
case THING_WAV:
SDL_free(thing->data.wav.buf);
break;
case THING_STREAM:
SDL_DestroyAudioStream(thing->data.stream.stream);
break;
@ -416,12 +456,12 @@ static const char *AudioFmtToString(const SDL_AudioFormat fmt)
#define FMTCASE(x) case SDL_AUDIO_##x: return #x
FMTCASE(U8);
FMTCASE(S8);
FMTCASE(S16LSB);
FMTCASE(S16MSB);
FMTCASE(S32LSB);
FMTCASE(S32MSB);
FMTCASE(F32LSB);
FMTCASE(F32MSB);
FMTCASE(S16LE);
FMTCASE(S16BE);
FMTCASE(S32LE);
FMTCASE(S32BE);
FMTCASE(F32LE);
FMTCASE(F32BE);
#undef FMTCASE
}
return "?";
@ -513,7 +553,7 @@ static void StreamThing_ontick(Thing *thing, Uint64 now)
if (!available || (SDL_GetAudioStreamFormat(thing->data.stream.stream, NULL, &spec) < 0)) {
DestroyThingInPoof(thing);
} else {
const int ticksleft = (int) ((((Uint64) ((available / (SDL_AUDIO_BITSIZE(spec.format) / 8)) / spec.channels)) * 1000) / spec.freq);
const int ticksleft = (int) ((((Uint64) (available / SDL_AUDIO_FRAMESIZE(spec))) * 1000) / spec.freq);
const float pct = thing->data.stream.total_ticks ? (((float) (ticksleft)) / ((float) thing->data.stream.total_ticks)) : 0.0f;
thing->progress = 1.0f - pct;
}
@ -553,7 +593,7 @@ static void StreamThing_ondrop(Thing *thing, int button, float x, float y)
SDL_UnbindAudioStream(thing->data.stream.stream); /* unbind from current device */
if (thing->line_connected_to->what == THING_LOGDEV_CAPTURE) {
SDL_FlushAudioStream(thing->data.stream.stream);
thing->data.stream.total_ticks = (int) (((((Uint64) (SDL_GetAudioStreamAvailable(thing->data.stream.stream) / (SDL_AUDIO_BITSIZE(spec->format) / 8))) / spec->channels) * 1000) / spec->freq);
thing->data.stream.total_ticks = (int) ((((Uint64) (SDL_GetAudioStreamAvailable(thing->data.stream.stream) / SDL_AUDIO_FRAMESIZE(*spec))) * 1000) / spec->freq);
}
}
@ -590,13 +630,13 @@ static void StreamThing_ondraw(Thing *thing, SDL_Renderer *renderer)
static Thing *CreateStreamThing(const SDL_AudioSpec *spec, const Uint8 *buf, const Uint32 buflen, const char *fname, const float x, const float y)
{
static const ThingType can_be_dropped_onto[] = { THING_TRASHCAN, THING_LOGDEV, THING_LOGDEV_CAPTURE, THING_NULL };
Thing *thing = CreateThing(THING_STREAM, x, y, 0, -1, -1, soundboard_texture, fname ? xstrdup(fname) : NULL);
Thing *thing = CreateThing(THING_STREAM, x, y, 0, -1, -1, soundboard_texture, fname);
SDL_Log("Adding audio stream for %s", fname ? fname : "(null)");
thing->data.stream.stream = SDL_CreateAudioStream(spec, spec);
if (buf && buflen) {
SDL_PutAudioStreamData(thing->data.stream.stream, buf, (int) buflen);
SDL_FlushAudioStream(thing->data.stream.stream);
thing->data.stream.total_ticks = (int) (((((Uint64) (SDL_GetAudioStreamAvailable(thing->data.stream.stream) / (SDL_AUDIO_BITSIZE(spec->format) / 8))) / spec->channels) * 1000) / spec->freq);
thing->data.stream.total_ticks = (int) ((((Uint64) (SDL_GetAudioStreamAvailable(thing->data.stream.stream) / SDL_AUDIO_FRAMESIZE(*spec))) * 1000) / spec->freq);
}
thing->ontick = StreamThing_ontick;
thing->ondrag = StreamThing_ondrag;
@ -656,6 +696,7 @@ static Thing *LoadWavThing(const char *fname, float x, float y)
SDL_asprintf(&titlebar, "WAV file (\"%s\", %s, %s, %uHz)", nodirs, AudioFmtToString(spec.format), AudioChansToStr(spec.channels), (unsigned int) spec.freq);
thing = CreateThing(THING_WAV, x - (audio_texture->w / 2), y - (audio_texture->h / 2), 5, -1, -1, audio_texture, titlebar);
SDL_free(titlebar);
SDL_memcpy(&thing->data.wav.spec, &spec, sizeof (SDL_AudioSpec));
thing->data.wav.buf = buf;
thing->data.wav.buflen = buflen;
@ -726,8 +767,10 @@ static void DeviceThing_ondrag(Thing *thing, int button, float x, float y)
static void SetLogicalDeviceTitlebar(Thing *thing)
{
SDL_AudioSpec *spec = &thing->data.logdev.spec;
SDL_GetAudioDeviceFormat(thing->data.logdev.devid, spec);
SDL_asprintf(&thing->titlebar, "Logical device #%u (%s, %s, %s, %uHz)", (unsigned int) thing->data.logdev.devid, thing->data.logdev.iscapture ? "CAPTURE" : "OUTPUT", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq);
int frames = 0;
SDL_GetAudioDeviceFormat(thing->data.logdev.devid, spec, &frames);
SDL_free(thing->titlebar);
SDL_asprintf(&thing->titlebar, "Logical device #%u (%s, %s, %s, %uHz, %d frames)", (unsigned int) thing->data.logdev.devid, thing->data.logdev.iscapture ? "CAPTURE" : "OUTPUT", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
}
static void LogicalDeviceThing_ondrop(Thing *thing, int button, float x, float y)
@ -739,6 +782,135 @@ static void LogicalDeviceThing_ondrop(Thing *thing, int button, float x, float y
}
}
static void SDLCALL PostmixCallback(void *userdata, const SDL_AudioSpec *spec, float *buffer, int buflen)
{
Thing *thing = (Thing *) userdata;
SDL_LockMutex(thing->data.logdev.postmix_lock);
if (thing->data.logdev.postmix_allocated < buflen) {
void *ptr = SDL_realloc(thing->data.logdev.postmix_buffer, buflen);
if (!ptr) {
SDL_UnlockMutex(thing->data.logdev.postmix_lock);
return; /* oh well. */
}
thing->data.logdev.postmix_buffer = (float *) ptr;
thing->data.logdev.postmix_allocated = buflen;
}
SDL_copyp(&thing->data.logdev.postmix_spec, spec);
SDL_memcpy(thing->data.logdev.postmix_buffer, buffer, buflen);
thing->data.logdev.postmix_buflen = buflen;
SDL_AtomicSet(&thing->data.logdev.postmix_updated, 1);
SDL_UnlockMutex(thing->data.logdev.postmix_lock);
}
static void UpdateVisualizer(SDL_Renderer *renderer, SDL_Texture *visualizer, const int channels, const float *buffer, const int buflen)
{
static const SDL_Color channel_colors[8] = {
{ 255, 255, 255, 255 },
{ 255, 0, 0, 255 },
{ 0, 255, 0, 255 },
{ 0, 0, 255, 255 },
{ 255, 255, 0, 255 },
{ 0, 255, 255, 255 },
{ 255, 0, 255, 255 },
{ 127, 127, 127, 255 }
};
SDL_SetRenderTarget(renderer, visualizer);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
if (buffer && buflen) {
const int frames = (buflen / sizeof (float)) / channels;
const int skip = frames / (VISUALIZER_WIDTH * 2);
int i, j;
for (i = channels - 1; i >= 0; i--) {
const SDL_Color *color = &channel_colors[i % SDL_arraysize(channel_colors)];
SDL_FPoint points[VISUALIZER_WIDTH + 2];
float prevx = 0.0f;
int pointidx = 1;
points[0].x = 0.0f;
points[0].y = VISUALIZER_HEIGHT * 0.5f;
for (j = 0; j < (SDL_arraysize(points)-1); j++) {
const float val = buffer[((j * skip) * channels) + i];
const float x = prevx + 2;
const float y = (VISUALIZER_HEIGHT * 0.5f) - (VISUALIZER_HEIGHT * (val * 0.5f));
SDL_assert(pointidx < SDL_arraysize(points));
points[pointidx].x = x;
points[pointidx].y = y;
pointidx++;
prevx = x;
}
SDL_SetRenderDrawColor(renderer, color->r, color->g, color->b, 255);
SDL_RenderLines(renderer, points, pointidx);
}
}
SDL_SetRenderTarget(renderer, NULL);
}
static void LogicalDeviceThing_ontick(Thing *thing, Uint64 now)
{
const SDL_bool ismousedover = (thing == mouseover_thing) ? SDL_TRUE : SDL_FALSE;
if (!thing->data.logdev.visualizer || !thing->data.logdev.postmix_lock) { /* need these to work, skip if they failed. */
return;
}
if (thing->data.logdev.visualizer_enabled != ismousedover) {
thing->data.logdev.visualizer_enabled = ismousedover;
if (!ismousedover) {
SDL_SetAudioPostmixCallback(thing->data.logdev.devid, NULL, NULL);
} else {
if (thing->data.logdev.postmix_buffer) {
SDL_memset(thing->data.logdev.postmix_buffer, '\0', thing->data.logdev.postmix_buflen);
}
SDL_AtomicSet(&thing->data.logdev.postmix_updated, 1); /* so this will at least clear the texture later. */
SDL_SetAudioPostmixCallback(thing->data.logdev.devid, PostmixCallback, thing);
}
}
}
static void LogicalDeviceThing_ondraw(Thing *thing, SDL_Renderer *renderer)
{
if (thing->data.logdev.visualizer_enabled) {
SDL_FRect dst;
dst.w = thing->rect.w;
dst.h = thing->rect.h;
dst.x = thing->rect.x + ((thing->rect.w - dst.w) / 2);
dst.y = thing->rect.y + ((thing->rect.h - dst.h) / 2);
if (SDL_AtomicGet(&thing->data.logdev.postmix_updated)) {
float *buffer;
int channels;
int buflen;
SDL_LockMutex(thing->data.logdev.postmix_lock);
channels = thing->data.logdev.postmix_spec.channels;
buflen = thing->data.logdev.postmix_buflen;
buffer = (float *) SDL_malloc(thing->data.logdev.postmix_buflen);
if (buffer) {
SDL_memcpy(buffer, thing->data.logdev.postmix_buffer, thing->data.logdev.postmix_buflen);
SDL_AtomicSet(&thing->data.logdev.postmix_updated, 0);
}
SDL_UnlockMutex(thing->data.logdev.postmix_lock);
UpdateVisualizer(renderer, thing->data.logdev.visualizer, channels, buffer, buflen);
SDL_free(buffer);
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 30);
SDL_RenderTexture(renderer, thing->data.logdev.visualizer, NULL, &dst);
}
}
static Thing *CreateLogicalDeviceThing(Thing *parent, const SDL_AudioDeviceID which, const float x, const float y)
{
static const ThingType can_be_dropped_onto[] = { THING_TRASHCAN, THING_NULL };
@ -751,9 +923,16 @@ static Thing *CreateLogicalDeviceThing(Thing *parent, const SDL_AudioDeviceID wh
thing->data.logdev.devid = which;
thing->data.logdev.iscapture = iscapture;
thing->data.logdev.physdev = physthing;
thing->data.logdev.visualizer = SDL_CreateTexture(state->renderers[0], SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, VISUALIZER_WIDTH, VISUALIZER_HEIGHT);
thing->data.logdev.postmix_lock = SDL_CreateMutex();
if (thing->data.logdev.visualizer) {
SDL_SetTextureBlendMode(thing->data.logdev.visualizer, SDL_BLENDMODE_BLEND);
}
thing->line_connected_to = physthing;
thing->ontick = LogicalDeviceThing_ontick;
thing->ondrag = DeviceThing_ondrag;
thing->ondrop = LogicalDeviceThing_ondrop;
thing->ondraw = LogicalDeviceThing_ondraw;
thing->can_be_dropped_onto = can_be_dropped_onto;
SetLogicalDeviceTitlebar(thing);
@ -762,14 +941,16 @@ static Thing *CreateLogicalDeviceThing(Thing *parent, const SDL_AudioDeviceID wh
static void SetPhysicalDeviceTitlebar(Thing *thing)
{
int frames = 0;
SDL_AudioSpec *spec = &thing->data.physdev.spec;
SDL_GetAudioDeviceFormat(thing->data.physdev.devid, spec);
SDL_GetAudioDeviceFormat(thing->data.physdev.devid, spec, &frames);
SDL_free(thing->titlebar);
if (thing->data.physdev.devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) {
SDL_asprintf(&thing->titlebar, "Default system device (CAPTURE, %s, %s, %uHz)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq);
SDL_asprintf(&thing->titlebar, "Default system device (CAPTURE, %s, %s, %uHz, %d frames)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
} else if (thing->data.physdev.devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) {
SDL_asprintf(&thing->titlebar, "Default system device (OUTPUT, %s, %s, %uHz)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq);
SDL_asprintf(&thing->titlebar, "Default system device (OUTPUT, %s, %s, %uHz, %d frames)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
} else {
SDL_asprintf(&thing->titlebar, "Physical device #%u (%s, \"%s\", %s, %s, %uHz)", (unsigned int) thing->data.physdev.devid, thing->data.physdev.iscapture ? "CAPTURE" : "OUTPUT", thing->data.physdev.name, AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq);
SDL_asprintf(&thing->titlebar, "Physical device #%u (%s, \"%s\", %s, %s, %uHz, %d frames)", (unsigned int) thing->data.physdev.devid, thing->data.physdev.iscapture ? "CAPTURE" : "OUTPUT", thing->data.physdev.name, AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
}
}
@ -965,7 +1146,7 @@ static void Loop(void)
case SDL_EVENT_AUDIO_DEVICE_ADDED:
CreatePhysicalDeviceThing(event.adevice.which, event.adevice.iscapture);
break;
case SDL_EVENT_AUDIO_DEVICE_REMOVED: {
const SDL_AudioDeviceID which = event.adevice.which;
Thing *i, *next;

View File

@ -28,8 +28,8 @@ static int done = 0;
static void loop(void)
{
const SDL_AudioDeviceID devid_in = SDL_GetAudioStreamBinding(stream_in);
const SDL_AudioDeviceID devid_out = SDL_GetAudioStreamBinding(stream_out);
const SDL_AudioDeviceID devid_in = SDL_GetAudioStreamDevice(stream_in);
const SDL_AudioDeviceID devid_out = SDL_GetAudioStreamDevice(stream_out);
SDL_bool please_quit = SDL_FALSE;
SDL_Event e;
@ -54,7 +54,7 @@ static void loop(void)
}
}
if (!SDL_IsAudioDevicePaused(devid_in)) {
if (!SDL_AudioDevicePaused(devid_in)) {
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
} else {
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
@ -179,12 +179,16 @@ int main(int argc, char **argv)
exit(1);
}
SDL_PauseAudioDevice(device);
SDL_GetAudioDeviceFormat(device, &outspec);
stream_out = SDL_CreateAndBindAudioStream(device, &outspec);
SDL_GetAudioDeviceFormat(device, &outspec, NULL);
stream_out = SDL_CreateAudioStream(&outspec, &outspec);
if (!stream_out) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create an audio stream for playback: %s!\n", SDL_GetError());
SDL_Quit();
exit(1);
} else if (SDL_BindAudioStream(device, stream_out) == -1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't bind an audio stream for playback: %s!\n", SDL_GetError());
SDL_Quit();
exit(1);
}
SDL_Log("Opening capture device %s%s%s...\n",
@ -199,12 +203,16 @@ int main(int argc, char **argv)
exit(1);
}
SDL_PauseAudioDevice(device);
SDL_GetAudioDeviceFormat(device, &inspec);
stream_in = SDL_CreateAndBindAudioStream(device, &inspec);
SDL_GetAudioDeviceFormat(device, &inspec, NULL);
stream_in = SDL_CreateAudioStream(&inspec, &inspec);
if (!stream_in) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create an audio stream for capture: %s!\n", SDL_GetError());
SDL_Quit();
exit(1);
} else if (SDL_BindAudioStream(device, stream_in) == -1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't bind an audio stream for capture: %s!\n", SDL_GetError());
SDL_Quit();
exit(1);
}
SDL_SetAudioStreamFormat(stream_in, NULL, &outspec); /* make sure we output at the playback format. */

View File

@ -69,7 +69,7 @@ static void iteration(void)
done = 1;
}
} else if (e.type == SDL_EVENT_AUDIO_DEVICE_ADDED) {
const SDL_AudioDeviceID which = (SDL_AudioDeviceID ) e.adevice.which;
const SDL_AudioDeviceID which = (SDL_AudioDeviceID) e.adevice.which;
const SDL_bool iscapture = e.adevice.iscapture ? SDL_TRUE : SDL_FALSE;
char *name = SDL_GetAudioDeviceName(which);
if (name != NULL) {
@ -80,20 +80,15 @@ static void iteration(void)
continue;
}
if (!iscapture) {
dev = SDL_OpenAudioDevice(which, &spec);
if (!dev) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open '%s': %s\n", name, SDL_GetError());
SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(which, &spec, NULL, NULL);
if (!stream) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create/bind an audio stream to %u ('%s'): %s", (unsigned int) which, name, SDL_GetError());
} else {
SDL_AudioStream *stream;
SDL_Log("Opened '%s' as %u\n", name, (unsigned int)dev);
stream = SDL_CreateAndBindAudioStream(dev, &spec);
if (!stream) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create/bind an audio stream to %u ('%s'): %s", (unsigned int) dev, name, SDL_GetError());
SDL_CloseAudioDevice(dev);
}
SDL_Log("Opened '%s' as %u\n", name, (unsigned int) which);
/* !!! FIXME: laziness, this used to loop the audio, but we'll just play it once for now on each connect. */
SDL_PutAudioStreamData(stream, sound, soundlen);
SDL_FlushAudioStream(stream);
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream));
/* !!! FIXME: this is leaking the stream for now. We'll wire it up to a dictionary or whatever later. */
}
}
@ -101,7 +96,7 @@ static void iteration(void)
} else if (e.type == SDL_EVENT_AUDIO_DEVICE_REMOVED) {
dev = (SDL_AudioDeviceID)e.adevice.which;
SDL_Log("%s device %u removed.\n", devtypestr(e.adevice.iscapture), (unsigned int)dev);
SDL_CloseAudioDevice(dev);
/* !!! FIXME: we need to keep track of our streams and destroy them here. */
}
}
}

View File

@ -19,6 +19,7 @@ print_devices(SDL_bool iscapture)
SDL_AudioSpec spec;
const char *typestr = ((iscapture) ? "capture" : "output");
int n = 0;
int frames;
SDL_AudioDeviceID *devices = iscapture ? SDL_GetAudioCaptureDevices(&n) : SDL_GetAudioOutputDevices(&n);
if (devices == NULL) {
@ -37,10 +38,11 @@ print_devices(SDL_bool iscapture)
SDL_Log(" %d Error: %s\n", i, SDL_GetError());
}
if (SDL_GetAudioDeviceFormat(devices[i], &spec) == 0) {
if (SDL_GetAudioDeviceFormat(devices[i], &spec, &frames) == 0) {
SDL_Log(" Sample Rate: %d\n", spec.freq);
SDL_Log(" Channels: %d\n", spec.channels);
SDL_Log(" SDL_AudioFormat: %X\n", spec.format);
SDL_Log(" Buffer Size: %d frames\n", frames);
}
}
SDL_Log("\n");
@ -53,6 +55,7 @@ int main(int argc, char **argv)
SDL_AudioSpec spec;
int i;
int n;
int frames;
SDLTest_CommonState *state;
/* Initialize test framework */
@ -92,22 +95,24 @@ int main(int argc, char **argv)
print_devices(SDL_FALSE);
print_devices(SDL_TRUE);
if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec) < 0) {
if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, &frames) < 0) {
SDL_Log("Error when calling SDL_GetAudioDeviceFormat(default output): %s\n", SDL_GetError());
} else {
SDL_Log("Default Output Device:\n");
SDL_Log("Sample Rate: %d\n", spec.freq);
SDL_Log("Channels: %d\n", spec.channels);
SDL_Log("SDL_AudioFormat: %X\n", spec.format);
SDL_Log("Buffer Size: %d frames\n", frames);
}
if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_CAPTURE, &spec) < 0) {
if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_CAPTURE, &spec, &frames) < 0) {
SDL_Log("Error when calling SDL_GetAudioDeviceFormat(default capture): %s\n", SDL_GetError());
} else {
SDL_Log("Default Capture Device:\n");
SDL_Log("Sample Rate: %d\n", spec.freq);
SDL_Log("Channels: %d\n", spec.channels);
SDL_Log("SDL_AudioFormat: %X\n", spec.format);
SDL_Log("Buffer Size: %d frames\n", frames);
}
SDL_Quit();

View File

@ -24,24 +24,198 @@
#include <stdlib.h>
#define SLIDER_WIDTH_PERC 500.f / 600.f
#define SLIDER_HEIGHT_PERC 100.f / 480.f
#define SLIDER_HEIGHT_PERC 70.f / 480.f
static int done;
static SDLTest_CommonState *state;
static int multiplier = 100;
static SDL_FRect slider_area;
static SDL_FRect slider_fill_area;
static SDL_AudioSpec spec;
static SDL_AudioStream *stream;
static Uint8 *audio_buf = NULL;
static Uint32 audio_len = 0;
static SDL_bool auto_loop = SDL_TRUE;
static SDL_bool auto_flush = SDL_FALSE;
static Uint64 last_get_callback = 0;
static int last_get_amount_additional = 0;
static int last_get_amount_total = 0;
typedef struct Slider
{
SDL_FRect area;
SDL_bool changed;
char fmtlabel[64];
float pos;
int flags;
float min;
float mid;
float max;
float value;
} Slider;
#define NUM_SLIDERS 3
Slider sliders[NUM_SLIDERS];
static int active_slider = -1;
static void init_slider(int index, const char* fmtlabel, int flags, float value, float min, float max)
{
Slider* slider = &sliders[index];
slider->area.x = state->window_w * (1.f - SLIDER_WIDTH_PERC) / 2;
slider->area.y = state->window_h * (0.2f + (index * SLIDER_HEIGHT_PERC * 1.4f));
slider->area.w = SLIDER_WIDTH_PERC * state->window_w;
slider->area.h = SLIDER_HEIGHT_PERC * state->window_h;
slider->changed = SDL_TRUE;
SDL_strlcpy(slider->fmtlabel, fmtlabel, SDL_arraysize(slider->fmtlabel));
slider->flags = flags;
slider->min = min;
slider->max = max;
slider->value = value;
if (slider->flags & 1) {
slider->pos = (value - slider->min + 0.5f) / (slider->max - slider->min + 1.0f);
} else {
slider->pos = 0.5f;
slider->mid = value;
}
}
static float lerp(float v0, float v1, float t)
{
return (1 - t) * v0 + t * v1;
}
static void draw_text(SDL_Renderer* renderer, int x, int y, const char* text)
{
SDL_SetRenderDrawColor(renderer, 0xFD, 0xF6, 0xE3, 0xFF);
SDLTest_DrawString(renderer, (float) x, (float) y, text);
}
static void draw_textf(SDL_Renderer* renderer, int x, int y, const char* fmt, ...)
{
char text[256];
va_list ap;
va_start(ap, fmt);
SDL_vsnprintf(text, SDL_arraysize(text), fmt, ap);
va_end(ap);
draw_text(renderer, x, y, text);
}
static void queue_audio()
{
Uint8* new_data = NULL;
int new_len = 0;
int retval = 0;
SDL_AudioSpec new_spec;
new_spec.format = spec.format;
new_spec.channels = (int) sliders[2].value;
new_spec.freq = (int) sliders[1].value;
SDL_Log("Converting audio from %i to %i", spec.freq, new_spec.freq);
retval = retval ? retval : SDL_ConvertAudioSamples(&spec, audio_buf, audio_len, &new_spec, &new_data, &new_len);
retval = retval ? retval : SDL_SetAudioStreamFormat(stream, &new_spec, NULL);
retval = retval ? retval : SDL_PutAudioStreamData(stream, new_data, new_len);
if (auto_flush) {
retval = retval ? retval : SDL_FlushAudioStream(stream);
}
SDL_free(new_data);
if (retval) {
SDL_Log("Failed to queue audio: %s", SDL_GetError());
} else {
SDL_Log("Queued audio");
}
}
static void skip_audio(float amount)
{
float speed;
SDL_AudioSpec dst_spec, new_spec;
int num_frames;
int retval = 0;
void* buf = NULL;
SDL_LockAudioStream(stream);
speed = SDL_GetAudioStreamFrequencyRatio(stream);
SDL_GetAudioStreamFormat(stream, NULL, &dst_spec);
/* Gimme that crunchy audio */
new_spec.format = SDL_AUDIO_S8;
new_spec.channels = 1;
new_spec.freq = 4000;
SDL_SetAudioStreamFrequencyRatio(stream, 100.0f);
SDL_SetAudioStreamFormat(stream, NULL, &new_spec);
num_frames = (int)(new_spec.freq * ((speed * amount) / 100.0f));
buf = SDL_malloc(num_frames);
if (buf != NULL) {
retval = SDL_GetAudioStreamData(stream, buf, num_frames);
SDL_free(buf);
}
SDL_SetAudioStreamFormat(stream, NULL, &dst_spec);
SDL_SetAudioStreamFrequencyRatio(stream, speed);
SDL_UnlockAudioStream(stream);
if (retval >= 0) {
SDL_Log("Skipped %.2f seconds", amount);
} else {
SDL_Log("Failed to skip: %s", SDL_GetError());
}
}
static const char *AudioFmtToString(const SDL_AudioFormat fmt)
{
switch (fmt) {
#define FMTCASE(x) case SDL_AUDIO_##x: return #x
FMTCASE(U8);
FMTCASE(S8);
FMTCASE(S16LE);
FMTCASE(S16BE);
FMTCASE(S32LE);
FMTCASE(S32BE);
FMTCASE(F32LE);
FMTCASE(F32BE);
#undef FMTCASE
}
return "?";
}
static const char *AudioChansToStr(const int channels)
{
switch (channels) {
case 1: return "Mono";
case 2: return "Stereo";
case 3: return "2.1";
case 4: return "Quad";
case 5: return "4.1";
case 6: return "5.1";
case 7: return "6.1";
case 8: return "7.1";
default: break;
}
return "?";
}
static void loop(void)
{
int i;
int i, j;
SDL_Event e;
int newmultiplier = multiplier;
SDL_FPoint p;
SDL_AudioSpec src_spec, dst_spec;
int available_bytes = 0;
float available_seconds = 0;
while (SDL_PollEvent(&e)) {
SDLTest_CommonEvent(state, &e, &done);
@ -50,63 +224,148 @@ static void loop(void)
emscripten_cancel_main_loop();
}
#endif
if (e.type == SDL_EVENT_MOUSE_MOTION) {
if (e.motion.state & SDL_BUTTON_LMASK) {
const SDL_FPoint p = { e.motion.x, e.motion.y };
if (SDL_PointInRectFloat(&p, &slider_area)) {
const float w = SDL_roundf(p.x - slider_area.x);
slider_fill_area.w = w;
newmultiplier = ((int) ((w / slider_area.w) * 800.0f)) - 400;
if (e.type == SDL_EVENT_KEY_DOWN) {
SDL_Keycode sym = e.key.keysym.sym;
if (sym == SDLK_q) {
if (SDL_AudioDevicePaused(state->audio_id)) {
SDL_ResumeAudioDevice(state->audio_id);
} else {
SDL_PauseAudioDevice(state->audio_id);
}
} else if (sym == SDLK_w) {
auto_loop = auto_loop ? SDL_FALSE : SDL_TRUE;
} else if (sym == SDLK_e) {
auto_flush = auto_flush ? SDL_FALSE : SDL_TRUE;
} else if (sym == SDLK_a) {
SDL_ClearAudioStream(stream);
SDL_Log("Cleared audio stream");
} else if (sym == SDLK_s) {
queue_audio();
} else if (sym == SDLK_d) {
float amount = 1.0f;
amount *= (e.key.keysym.mod & SDL_KMOD_CTRL) ? 10.0f : 1.0f;
amount *= (e.key.keysym.mod & SDL_KMOD_SHIFT) ? 10.0f : 1.0f;
skip_audio(amount);
}
}
}
if (multiplier != newmultiplier) {
SDL_AudioSpec newspec;
char title[64];
int newfreq = spec.freq;
multiplier = newmultiplier;
if (multiplier == 0) {
SDL_snprintf(title, sizeof (title), "Drag the slider: Normal speed");
} else if (multiplier < 0) {
SDL_snprintf(title, sizeof (title), "Drag the slider: %.2fx slow", (-multiplier / 100.0f) + 1.0f);
} else {
SDL_snprintf(title, sizeof (title), "Drag the slider: %.2fx fast", (multiplier / 100.0f) + 1.0f);
if (SDL_GetMouseState(&p.x, &p.y) & SDL_BUTTON_LMASK) {
if (active_slider == -1) {
for (i = 0; i < NUM_SLIDERS; ++i) {
if (SDL_PointInRectFloat(&p, &sliders[i].area)) {
active_slider = i;
break;
}
}
}
for (i = 0; i < state->num_windows; i++) {
SDL_SetWindowTitle(state->windows[i], title);
}
/* this math sucks, but whatever. */
if (multiplier < 0) {
newfreq = spec.freq + (int) ((spec.freq * (multiplier / 400.0f)) * 0.75f);
} else if (multiplier > 0) {
newfreq = spec.freq + (int) (spec.freq * (multiplier / 100.0f));
}
/* SDL_Log("newfreq=%d multiplier=%d\n", newfreq, multiplier); */
SDL_memcpy(&newspec, &spec, sizeof (spec));
newspec.freq = newfreq;
SDL_SetAudioStreamFormat(stream, &newspec, NULL);
} else {
active_slider = -1;
}
/* keep it looping. */
if (SDL_GetAudioStreamAvailable(stream) < ((int) (audio_len / 2))) {
SDL_PutAudioStreamData(stream, audio_buf, audio_len);
if (active_slider != -1) {
Slider* slider = &sliders[active_slider];
float value = (p.x - slider->area.x) / slider->area.w;
value = SDL_clamp(value, 0.0f, 1.0f);
slider->pos = value;
if (slider->flags & 1) {
value = slider->min + (value * (slider->max - slider->min + 1.0f));
value = SDL_clamp(value, slider->min, slider->max);
} else {
value = (value * 2.0f) - 1.0f;
value = (value >= 0)
? lerp(slider->mid, slider->max, value)
: lerp(slider->mid, slider->min, -value);
}
if (value != slider->value) {
slider->value = value;
slider->changed = SDL_TRUE;
}
}
if (sliders[0].changed) {
sliders[0].changed = SDL_FALSE;
SDL_SetAudioStreamFrequencyRatio(stream, sliders[0].value);
}
if (SDL_GetAudioStreamFormat(stream, &src_spec, &dst_spec) == 0) {
available_bytes = SDL_GetAudioStreamAvailable(stream);
available_seconds = (float)available_bytes / (float)(SDL_AUDIO_FRAMESIZE(dst_spec) * dst_spec.freq);
/* keep it looping. */
if (auto_loop && (available_seconds < 10.0f)) {
queue_audio();
}
}
for (i = 0; i < state->num_windows; i++) {
SDL_SetRenderDrawColor(state->renderers[i], 0, 0, 255, 255);
SDL_RenderClear(state->renderers[i]);
SDL_SetRenderDrawColor(state->renderers[i], 0, 0, 0, 255);
SDL_RenderFillRect(state->renderers[i], &slider_area);
SDL_SetRenderDrawColor(state->renderers[i], 255, 0, 0, 255);
SDL_RenderFillRect(state->renderers[i], &slider_fill_area);
SDL_RenderPresent(state->renderers[i]);
int draw_y = 0;
SDL_Renderer* rend = state->renderers[i];
SDL_SetRenderDrawColor(rend, 0x00, 0x2B, 0x36, 0xFF);
SDL_RenderClear(rend);
for (j = 0; j < NUM_SLIDERS; ++j) {
Slider* slider = &sliders[j];
SDL_FRect area;
SDL_copyp(&area, &slider->area);
SDL_SetRenderDrawColor(rend, 0x07, 0x36, 0x42, 0xFF);
SDL_RenderFillRect(rend, &area);
area.w *= slider->pos;
SDL_SetRenderDrawColor(rend, 0x58, 0x6E, 0x75, 0xFF);
SDL_RenderFillRect(rend, &area);
draw_textf(rend, (int)slider->area.x, (int)slider->area.y, slider->fmtlabel,
(slider->flags & 2) ? ((float)(int)slider->value) : slider->value);
}
draw_textf(rend, 0, draw_y, "%7s, Loop: %3s, Flush: %3s",
SDL_AudioDevicePaused(state->audio_id) ? "Paused" : "Playing", auto_loop ? "On" : "Off", auto_flush ? "On" : "Off");
draw_y += FONT_LINE_HEIGHT;
draw_textf(rend, 0, draw_y, "Available: %4.2f (%i bytes)", available_seconds, available_bytes);
draw_y += FONT_LINE_HEIGHT;
SDL_LockAudioStream(stream);
draw_textf(rend, 0, draw_y, "Get Callback: %i/%i bytes, %2i ms ago",
last_get_amount_additional, last_get_amount_total, (int)(SDL_GetTicks() - last_get_callback));
draw_y += FONT_LINE_HEIGHT;
SDL_UnlockAudioStream(stream);
draw_y = state->window_h - FONT_LINE_HEIGHT * 3;
draw_textf(rend, 0, draw_y, "Wav: %6s/%6s/%i",
AudioFmtToString(spec.format), AudioChansToStr(spec.channels), spec.freq);
draw_y += FONT_LINE_HEIGHT;
draw_textf(rend, 0, draw_y, "Src: %6s/%6s/%i",
AudioFmtToString(src_spec.format), AudioChansToStr(src_spec.channels), src_spec.freq);
draw_y += FONT_LINE_HEIGHT;
draw_textf(rend, 0, draw_y, "Dst: %6s/%6s/%i",
AudioFmtToString(dst_spec.format), AudioChansToStr(dst_spec.channels), dst_spec.freq);
draw_y += FONT_LINE_HEIGHT;
SDL_RenderPresent(rend);
}
}
static void SDLCALL our_get_callback(void *userdata, SDL_AudioStream *strm, int additional_amount, int total_amount)
{
last_get_callback = SDL_GetTicks();
last_get_amount_additional = additional_amount;
last_get_amount_total = total_amount;
}
int main(int argc, char *argv[])
{
char *filename = NULL;
@ -142,20 +401,14 @@ int main(int argc, char *argv[])
i += consumed;
}
slider_area.x = state->window_w * (1.f - SLIDER_WIDTH_PERC) / 2;
slider_area.y = state->window_h * (1.f - SLIDER_HEIGHT_PERC) / 2;
slider_area.w = SLIDER_WIDTH_PERC * state->window_w;
slider_area.h = SLIDER_HEIGHT_PERC * state->window_h;
slider_fill_area = slider_area;
slider_fill_area.w /= 2;
/* Load the SDL library */
if (!SDLTest_CommonInit(state)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
return 1;
}
FONT_CHARACTER_SIZE = 16;
filename = GetResourceFilename(filename, "sample.wav");
rc = SDL_LoadWAV(filename, &spec, &audio_buf, &audio_len);
SDL_free(filename);
@ -166,12 +419,17 @@ int main(int argc, char *argv[])
return 1;
}
init_slider(0, "Speed: %3.2fx", 0x0, 1.0f, 0.2f, 5.0f);
init_slider(1, "Freq: %g", 0x2, (float)spec.freq, 4000.0f, 192000.0f);
init_slider(2, "Channels: %g", 0x3, (float)spec.channels, 1.0f, 8.0f);
for (i = 0; i < state->num_windows; i++) {
SDL_SetWindowTitle(state->windows[i], "Drag the slider: Normal speed");
SDL_SetWindowTitle(state->windows[i], "Resampler Test");
}
stream = SDL_CreateAudioStream(&spec, &spec);
SDL_PutAudioStreamData(stream, audio_buf, audio_len);
SDL_SetAudioStreamGetCallback(stream, our_get_callback, NULL);
SDL_BindAudioStream(state->audio_id, stream);
#ifdef __EMSCRIPTEN__
@ -182,10 +440,10 @@ int main(int argc, char *argv[])
}
#endif
SDLTest_CleanupTextDrawing();
SDL_DestroyAudioStream(stream);
SDL_free(audio_buf);
SDLTest_CommonQuit(state);
SDL_Quit();
return 0;
}

View File

@ -176,13 +176,13 @@ static int audio_initOpenCloseQuitAudio(void *arg)
case 0:
/* Set standard desired spec */
desired.freq = 22050;
desired.format = SDL_AUDIO_S16SYS;
desired.format = SDL_AUDIO_S16;
desired.channels = 2;
case 1:
/* Set custom desired spec */
desired.freq = 48000;
desired.format = SDL_AUDIO_F32SYS;
desired.format = SDL_AUDIO_F32;
desired.channels = 2;
break;
}
@ -261,14 +261,14 @@ static int audio_pauseUnpauseAudio(void *arg)
case 0:
/* Set standard desired spec */
desired.freq = 22050;
desired.format = SDL_AUDIO_S16SYS;
desired.format = SDL_AUDIO_S16;
desired.channels = 2;
break;
case 1:
/* Set custom desired spec */
desired.freq = 48000;
desired.format = SDL_AUDIO_F32SYS;
desired.format = SDL_AUDIO_F32;
desired.channels = 2;
break;
}
@ -441,18 +441,34 @@ static int audio_printCurrentAudioDriver(void *arg)
}
/* Definition of all formats, channels, and frequencies used to test audio conversions */
static SDL_AudioFormat g_audioFormats[] = { SDL_AUDIO_S8, SDL_AUDIO_U8, SDL_AUDIO_S16LSB, SDL_AUDIO_S16MSB, SDL_AUDIO_S16SYS, SDL_AUDIO_S16,
SDL_AUDIO_S32LSB, SDL_AUDIO_S32MSB, SDL_AUDIO_S32SYS, SDL_AUDIO_S32,
SDL_AUDIO_F32LSB, SDL_AUDIO_F32MSB, SDL_AUDIO_F32SYS, SDL_AUDIO_F32 };
static const char *g_audioFormatsVerbose[] = { "SDL_AUDIO_S8", "SDL_AUDIO_U8", "SDL_AUDIO_S16LSB", "SDL_AUDIO_S16MSB", "SDL_AUDIO_S16SYS", "SDL_AUDIO_S16",
"SDL_AUDIO_S32LSB", "SDL_AUDIO_S32MSB", "SDL_AUDIO_S32SYS", "SDL_AUDIO_S32",
"SDL_AUDIO_F32LSB", "SDL_AUDIO_F32MSB", "SDL_AUDIO_F32SYS", "SDL_AUDIO_F32" };
static SDL_AudioFormat g_audioFormats[] = {
SDL_AUDIO_S8, SDL_AUDIO_U8,
SDL_AUDIO_S16LE, SDL_AUDIO_S16BE,
SDL_AUDIO_S32LE, SDL_AUDIO_S32BE,
SDL_AUDIO_F32LE, SDL_AUDIO_F32BE
};
static const char *g_audioFormatsVerbose[] = {
"SDL_AUDIO_S8", "SDL_AUDIO_U8",
"SDL_AUDIO_S16LE", "SDL_AUDIO_S16BE",
"SDL_AUDIO_S32LE", "SDL_AUDIO_S32BE",
"SDL_AUDIO_F32LE", "SDL_AUDIO_F32BE"
};
static const int g_numAudioFormats = SDL_arraysize(g_audioFormats);
static Uint8 g_audioChannels[] = { 1, 2, 4, 6 };
static const int g_numAudioChannels = SDL_arraysize(g_audioChannels);
static int g_audioFrequencies[] = { 11025, 22050, 44100, 48000 };
static const int g_numAudioFrequencies = SDL_arraysize(g_audioFrequencies);
/* Verify the audio formats are laid out as expected */
SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_U8_FORMAT, SDL_AUDIO_U8 == SDL_AUDIO_BITSIZE(8));
SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_S8_FORMAT, SDL_AUDIO_S8 == (SDL_AUDIO_BITSIZE(8) | SDL_AUDIO_MASK_SIGNED));
SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_S16LE_FORMAT, SDL_AUDIO_S16LE == (SDL_AUDIO_BITSIZE(16) | SDL_AUDIO_MASK_SIGNED));
SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_S16BE_FORMAT, SDL_AUDIO_S16BE == (SDL_AUDIO_S16LE | SDL_AUDIO_MASK_BIG_ENDIAN));
SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_S32LE_FORMAT, SDL_AUDIO_S32LE == (SDL_AUDIO_BITSIZE(32) | SDL_AUDIO_MASK_SIGNED));
SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_S32BE_FORMAT, SDL_AUDIO_S32BE == (SDL_AUDIO_S32LE | SDL_AUDIO_MASK_BIG_ENDIAN));
SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_F32LE_FORMAT, SDL_AUDIO_F32LE == (SDL_AUDIO_BITSIZE(32) | SDL_AUDIO_MASK_FLOAT | SDL_AUDIO_MASK_SIGNED));
SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_F32BE_FORMAT, SDL_AUDIO_F32BE == (SDL_AUDIO_F32LE | SDL_AUDIO_MASK_BIG_ENDIAN));
/**
* \brief Builds various audio conversion structures
*
@ -466,7 +482,7 @@ static int audio_buildAudioStream(void *arg)
int i, ii, j, jj, k, kk;
/* No conversion needed */
spec1.format = SDL_AUDIO_S16LSB;
spec1.format = SDL_AUDIO_S16LE;
spec1.channels = 2;
spec1.freq = 22050;
stream = SDL_CreateAudioStream(&spec1, &spec1);
@ -478,7 +494,7 @@ static int audio_buildAudioStream(void *arg)
spec1.format = SDL_AUDIO_S8;
spec1.channels = 1;
spec1.freq = 22050;
spec2.format = SDL_AUDIO_S16LSB;
spec2.format = SDL_AUDIO_S16LE;
spec2.channels = 2;
spec2.freq = 44100;
stream = SDL_CreateAudioStream(&spec1, &spec2);
@ -533,7 +549,7 @@ static int audio_buildAudioStreamNegative(void *arg)
spec1.format = SDL_AUDIO_S8;
spec1.channels = 1;
spec1.freq = 22050;
spec2.format = SDL_AUDIO_S16LSB;
spec2.format = SDL_AUDIO_S16LE;
spec2.channels = 2;
spec2.freq = 44100;
@ -546,7 +562,7 @@ static int audio_buildAudioStreamNegative(void *arg)
spec1.format = SDL_AUDIO_S8;
spec1.channels = 1;
spec1.freq = 22050;
spec2.format = SDL_AUDIO_S16LSB;
spec2.format = SDL_AUDIO_S16LE;
spec2.channels = 2;
spec2.freq = 44100;
@ -692,54 +708,65 @@ static int audio_convertAudio(void *arg)
} else {
Uint8 *dst_buf = NULL, *src_buf = NULL;
int dst_len = 0, src_len = 0, real_dst_len = 0;
int l = 64;
int src_samplesize, dst_samplesize;
int l = 64, m;
int src_framesize, dst_framesize;
int src_silence, dst_silence;
src_samplesize = (SDL_AUDIO_BITSIZE(spec1.format) / 8) * spec1.channels;
dst_samplesize = (SDL_AUDIO_BITSIZE(spec2.format) / 8) * spec2.channels;
src_framesize = SDL_AUDIO_FRAMESIZE(spec1);
dst_framesize = SDL_AUDIO_FRAMESIZE(spec2);
/* Create some random data to convert */
src_len = l * src_samplesize;
src_len = l * src_framesize;
SDLTest_Log("Creating dummy sample buffer of %i length (%i bytes)", l, src_len);
src_buf = (Uint8 *)SDL_malloc(src_len);
SDLTest_AssertCheck(dst_buf != NULL, "Check src data buffer to convert is not NULL");
SDLTest_AssertCheck(src_buf != NULL, "Check src data buffer to convert is not NULL");
if (src_buf == NULL) {
return TEST_ABORTED;
}
src_len = src_len & ~(src_samplesize - 1);
dst_len = dst_samplesize * (src_len / src_samplesize);
if (spec1.freq < spec2.freq) {
const double mult = ((double)spec2.freq) / ((double)spec1.freq);
dst_len *= (int) SDL_ceil(mult);
}
src_silence = SDL_GetSilenceValueForFormat(spec1.format);
SDL_memset(src_buf, src_silence, src_len);
dst_len = dst_len & ~(dst_samplesize - 1);
dst_buf = (Uint8 *)SDL_calloc(1, dst_len);
dst_len = ((int)((((Sint64)l * spec2.freq) - 1) / spec1.freq) + 1) * dst_framesize;
dst_buf = (Uint8 *)SDL_malloc(dst_len);
SDLTest_AssertCheck(dst_buf != NULL, "Check dst data buffer to convert is not NULL");
if (dst_buf == NULL) {
return TEST_ABORTED;
}
real_dst_len = SDL_GetAudioStreamAvailable(stream);
SDLTest_AssertCheck(0 == real_dst_len, "Verify available (pre-put); expected: %i; got: %i", 0, real_dst_len);
/* Run the audio converter */
if (SDL_PutAudioStreamData(stream, src_buf, src_len) < 0 ||
SDL_FlushAudioStream(stream) < 0) {
return TEST_ABORTED;
}
real_dst_len = SDL_GetAudioStreamAvailable(stream);
SDLTest_AssertCheck(dst_len == real_dst_len, "Verify available (post-put); expected: %i; got: %i", dst_len, real_dst_len);
real_dst_len = SDL_GetAudioStreamData(stream, dst_buf, dst_len);
SDLTest_AssertCheck(real_dst_len > 0, "Verify result value; expected: > 0; got: %i", real_dst_len);
if (real_dst_len < 0) {
SDLTest_AssertCheck(dst_len == real_dst_len, "Verify result value; expected: %i; got: %i", dst_len, real_dst_len);
if (dst_len != real_dst_len) {
return TEST_ABORTED;
}
real_dst_len = SDL_GetAudioStreamAvailable(stream);
SDLTest_AssertCheck(0 == real_dst_len, "Verify available (post-get); expected: %i; got: %i", 0, real_dst_len);
dst_silence = SDL_GetSilenceValueForFormat(spec2.format);
for (m = 0; m < dst_len; ++m) {
if (dst_buf[m] != dst_silence) {
SDLTest_LogError("Output buffer is not silent");
return TEST_ABORTED;
}
}
SDL_DestroyAudioStream(stream);
/* Free converted buffer */
SDL_free(src_buf);
SDL_free(dst_buf);
}
}
}
@ -794,24 +821,30 @@ static int audio_resampleLoss(void *arg)
double signal_to_noise;
double max_error;
} test_specs[] = {
{ 50, 440, 0, 44100, 48000, 60, 0.0025 },
{ 50, 5000, SDL_PI_D / 2, 20000, 10000, 65, 0.0010 },
{ 50, 440, 0, 44100, 48000, 80, 0.0009 },
{ 50, 5000, SDL_PI_D / 2, 20000, 10000, 999, 0.0001 },
{ 50, 440, 0, 22050, 96000, 79, 0.0120 },
{ 50, 440, 0, 96000, 22050, 80, 0.0002 },
{ 0 }
};
int spec_idx = 0;
int min_channels = 1;
int max_channels = 1 /*8*/;
int num_channels = min_channels;
for (spec_idx = 0; test_specs[spec_idx].time > 0; ++spec_idx) {
for (spec_idx = 0; test_specs[spec_idx].time > 0;) {
const struct test_spec_t *spec = &test_specs[spec_idx];
const int frames_in = spec->time * spec->rate_in;
const int frames_target = spec->time * spec->rate_out;
const int len_in = frames_in * (int)sizeof(float);
const int len_target = frames_target * (int)sizeof(float);
const int len_in = (frames_in * num_channels) * (int)sizeof(float);
const int len_target = (frames_target * num_channels) * (int)sizeof(float);
SDL_AudioSpec tmpspec1, tmpspec2;
Uint64 tick_beg = 0;
Uint64 tick_end = 0;
int i = 0;
int j = 0;
int ret = 0;
SDL_AudioStream *stream = NULL;
float *buf_in = NULL;
@ -826,10 +859,10 @@ static int audio_resampleLoss(void *arg)
spec->time, spec->freq, spec->phase, spec->rate_in, spec->rate_out);
tmpspec1.format = SDL_AUDIO_F32;
tmpspec1.channels = 1;
tmpspec1.channels = num_channels;
tmpspec1.freq = spec->rate_in;
tmpspec2.format = SDL_AUDIO_F32;
tmpspec2.channels = 1;
tmpspec2.channels = num_channels;
tmpspec2.freq = spec->rate_out;
stream = SDL_CreateAudioStream(&tmpspec1, &tmpspec2);
SDLTest_AssertPass("Call to SDL_CreateAudioStream(SDL_AUDIO_F32, 1, %i, SDL_AUDIO_F32, 1, %i)", spec->rate_in, spec->rate_out);
@ -846,7 +879,10 @@ static int audio_resampleLoss(void *arg)
}
for (i = 0; i < frames_in; ++i) {
*(buf_in + i) = (float)sine_wave_sample(i, spec->rate_in, spec->freq, spec->phase);
float f = (float)sine_wave_sample(i, spec->rate_in, spec->freq, spec->phase);
for (j = 0; j < num_channels; ++j) {
*(buf_in + (i * num_channels) + j) = f;
}
}
tick_beg = SDL_GetPerformanceCounter();
@ -877,9 +913,7 @@ static int audio_resampleLoss(void *arg)
len_out = SDL_GetAudioStreamData(stream, buf_out, len_target);
SDLTest_AssertPass("Call to SDL_GetAudioStreamData(stream, buf_out, %i)", len_target);
/** !!! FIXME: SDL_AudioStream does not return output of the same length as
** !!! FIXME: the input even if SDL_FlushAudioStream is called. */
SDLTest_AssertCheck(len_out <= len_target, "Expected output length to be no larger than %i, got %i.",
SDLTest_AssertCheck(len_out == len_target, "Expected output length to be no larger than %i, got %i.",
len_target, len_out);
SDL_DestroyAudioStream(stream);
if (len_out > len_target) {
@ -890,13 +924,15 @@ static int audio_resampleLoss(void *arg)
tick_end = SDL_GetPerformanceCounter();
SDLTest_Log("Resampling used %f seconds.", ((double)(tick_end - tick_beg)) / SDL_GetPerformanceFrequency());
for (i = 0; i < len_out / (int)sizeof(float); ++i) {
const float output = *(buf_out + i);
for (i = 0; i < frames_target; ++i) {
const double target = sine_wave_sample(i, spec->rate_out, spec->freq, spec->phase);
const double error = SDL_fabs(target - output);
max_error = SDL_max(max_error, error);
sum_squared_error += error * error;
sum_squared_value += target * target;
for (j = 0; j < num_channels; ++j) {
const float output = *(buf_out + (i * num_channels) + j);
const double error = SDL_fabs(target - output);
max_error = SDL_max(max_error, error);
sum_squared_error += error * error;
sum_squared_value += target * target;
}
}
SDL_free(buf_out);
signal_to_noise = 10 * SDL_log10(sum_squared_value / sum_squared_error); /* decibel */
@ -909,10 +945,303 @@ static int audio_resampleLoss(void *arg)
signal_to_noise, spec->signal_to_noise);
SDLTest_AssertCheck(max_error <= spec->max_error, "Maximum conversion error %f should be no more than %f.",
max_error, spec->max_error);
if (++num_channels > max_channels) {
num_channels = min_channels;
++spec_idx;
}
}
return TEST_COMPLETED;
}
/**
* \brief Check accuracy converting between audio formats.
*
* \sa SDL_ConvertAudioSamples
*/
static int audio_convertAccuracy(void *arg)
{
static SDL_AudioFormat formats[] = { SDL_AUDIO_S8, SDL_AUDIO_U8, SDL_AUDIO_S16, SDL_AUDIO_S32 };
static const char* format_names[] = { "S8", "U8", "S16", "S32" };
int src_num = 65537 + 2048 + 48 + 256 + 100000;
int src_len = src_num * sizeof(float);
float* src_data = SDL_malloc(src_len);
int i, j;
SDLTest_AssertCheck(src_data != NULL, "Expected source buffer to be created.");
if (src_data == NULL) {
return TEST_ABORTED;
}
j = 0;
/* Generate a uniform range of floats between [-1.0, 1.0] */
for (i = 0; i < 65537; ++i) {
src_data[j++] = ((float)i - 32768.0f) / 32768.0f;
}
/* Generate floats close to 1.0 */
const float max_val = 16777216.0f;
for (i = 0; i < 1024; ++i) {
float f = (max_val + (float)(512 - i)) / max_val;
src_data[j++] = f;
src_data[j++] = -f;
}
for (i = 0; i < 24; ++i) {
float f = (max_val + (float)(3u << i)) / max_val;
src_data[j++] = f;
src_data[j++] = -f;
}
/* Generate floats far outside the [-1.0, 1.0] range */
for (i = 0; i < 128; ++i) {
float f = 2.0f + (float) i;
src_data[j++] = f;
src_data[j++] = -f;
}
/* Fill the rest with random floats between [-1.0, 1.0] */
for (i = 0; i < 100000; ++i) {
src_data[j++] = SDLTest_RandomSint32() / 2147483648.0f;
}
/* Shuffle the data for good measure */
for (i = src_num - 1; i > 0; --i) {
float f = src_data[i];
j = SDLTest_RandomIntegerInRange(0, i);
src_data[i] = src_data[j];
src_data[j] = f;
}
for (i = 0; i < SDL_arraysize(formats); ++i) {
SDL_AudioSpec src_spec, tmp_spec;
Uint64 convert_begin, convert_end;
Uint8 *tmp_data, *dst_data;
int tmp_len, dst_len;
int ret;
SDL_AudioFormat format = formats[i];
const char* format_name = format_names[i];
/* Formats with > 23 bits can represent every value exactly */
float min_delta = 1.0f;
float max_delta = -1.0f;
/* Subtract 1 bit to account for sign */
int bits = SDL_AUDIO_BITSIZE(format) - 1;
float target_max_delta = (bits > 23) ? 0.0f : (1.0f / (float)(1 << bits));
float target_min_delta = -target_max_delta;
src_spec.format = SDL_AUDIO_F32;
src_spec.channels = 1;
src_spec.freq = 44100;
tmp_spec.format = format;
tmp_spec.channels = 1;
tmp_spec.freq = 44100;
convert_begin = SDL_GetPerformanceCounter();
tmp_data = NULL;
tmp_len = 0;
ret = SDL_ConvertAudioSamples(&src_spec, (const Uint8*) src_data, src_len, &tmp_spec, &tmp_data, &tmp_len);
SDLTest_AssertCheck(ret == 0, "Expected SDL_ConvertAudioSamples(F32->%s) to succeed", format_name);
if (ret != 0) {
SDL_free(src_data);
return TEST_ABORTED;
}
dst_data = NULL;
dst_len = 0;
ret = SDL_ConvertAudioSamples(&tmp_spec, tmp_data, tmp_len, &src_spec, &dst_data, &dst_len);
SDLTest_AssertCheck(ret == 0, "Expected SDL_ConvertAudioSamples(%s->F32) to succeed", format_name);
if (ret != 0) {
SDL_free(tmp_data);
SDL_free(src_data);
return TEST_ABORTED;
}
convert_end = SDL_GetPerformanceCounter();
SDLTest_Log("Conversion via %s took %f seconds.", format_name, ((double)(convert_end - convert_begin)) / SDL_GetPerformanceFrequency());
SDL_free(tmp_data);
for (j = 0; j < src_num; ++j) {
float x = src_data[j];
float y = ((float*)dst_data)[j];
float d = SDL_clamp(x, -1.0f, 1.0f) - y;
min_delta = SDL_min(min_delta, d);
max_delta = SDL_max(max_delta, d);
}
SDLTest_AssertCheck(min_delta >= target_min_delta, "%s has min delta of %+f, should be >= %+f", format_name, min_delta, target_min_delta);
SDLTest_AssertCheck(max_delta <= target_max_delta, "%s has max delta of %+f, should be <= %+f", format_name, max_delta, target_max_delta);
SDL_free(dst_data);
}
SDL_free(src_data);
return TEST_COMPLETED;
}
/**
* \brief Check accuracy when switching between formats
*
* \sa SDL_SetAudioStreamFormat
*/
static int audio_formatChange(void *arg)
{
int i;
SDL_AudioSpec spec1, spec2, spec3;
int frames_1, frames_2, frames_3;
int length_1, length_2, length_3;
int retval = 0;
int status = TEST_ABORTED;
float* buffer_1 = NULL;
float* buffer_2 = NULL;
float* buffer_3 = NULL;
SDL_AudioStream* stream = NULL;
double max_error = 0;
double sum_squared_error = 0;
double sum_squared_value = 0;
double signal_to_noise = 0;
double target_max_error = 0.02;
double target_signal_to_noise = 75.0;
int sine_freq = 500;
spec1.format = SDL_AUDIO_F32;
spec1.channels = 1;
spec1.freq = 20000;
spec2.format = SDL_AUDIO_F32;
spec2.channels = 1;
spec2.freq = 40000;
spec3.format = SDL_AUDIO_F32;
spec3.channels = 1;
spec3.freq = 80000;
frames_1 = spec1.freq;
frames_2 = spec2.freq;
frames_3 = spec3.freq * 2;
length_1 = (int)(frames_1 * sizeof(*buffer_1));
buffer_1 = (float*) SDL_malloc(length_1);
if (!SDLTest_AssertCheck(buffer_1 != NULL, "Expected buffer_1 to be created.")) {
goto cleanup;
}
length_2 = (int)(frames_2 * sizeof(*buffer_2));
buffer_2 = (float*) SDL_malloc(length_2);
if (!SDLTest_AssertCheck(buffer_2 != NULL, "Expected buffer_2 to be created.")) {
goto cleanup;
}
length_3 = (int)(frames_3 * sizeof(*buffer_3));
buffer_3 = (float*) SDL_malloc(length_3);
if (!SDLTest_AssertCheck(buffer_3 != NULL, "Expected buffer_3 to be created.")) {
goto cleanup;
}
for (i = 0; i < frames_1; ++i) {
buffer_1[i] = (float) sine_wave_sample(i, spec1.freq, sine_freq, 0.0f);
}
for (i = 0; i < frames_2; ++i) {
buffer_2[i] = (float) sine_wave_sample(i, spec2.freq, sine_freq, 0.0f);
}
stream = SDL_CreateAudioStream(NULL, NULL);
if (!SDLTest_AssertCheck(stream != NULL, "Expected SDL_CreateAudioStream to succeed")) {
goto cleanup;
}
retval = SDL_SetAudioStreamFormat(stream, &spec1, &spec3);
if (!SDLTest_AssertCheck(retval == 0, "Expected SDL_SetAudioStreamFormat(spec1, spec3) to succeed")) {
goto cleanup;
}
retval = SDL_GetAudioStreamAvailable(stream);
if (!SDLTest_AssertCheck(retval == 0, "Expected SDL_GetAudioStreamAvailable return 0")) {
goto cleanup;
}
retval = SDL_PutAudioStreamData(stream, buffer_1, length_1);
if (!SDLTest_AssertCheck(retval == 0, "Expected SDL_PutAudioStreamData(buffer_1) to succeed")) {
goto cleanup;
}
retval = SDL_FlushAudioStream(stream);
if (!SDLTest_AssertCheck(retval == 0, "Expected SDL_FlushAudioStream to succeed")) {
goto cleanup;
}
retval = SDL_SetAudioStreamFormat(stream, &spec2, &spec3);
if (!SDLTest_AssertCheck(retval == 0, "Expected SDL_SetAudioStreamFormat(spec2, spec3) to succeed")) {
goto cleanup;
}
retval = SDL_PutAudioStreamData(stream, buffer_2, length_2);
if (!SDLTest_AssertCheck(retval == 0, "Expected SDL_PutAudioStreamData(buffer_1) to succeed")) {
goto cleanup;
}
retval = SDL_FlushAudioStream(stream);
if (!SDLTest_AssertCheck(retval == 0, "Expected SDL_FlushAudioStream to succeed")) {
goto cleanup;
}
retval = SDL_GetAudioStreamAvailable(stream);
if (!SDLTest_AssertCheck(retval == length_3, "Expected SDL_GetAudioStreamAvailable to return %i, got %i", length_3, retval)) {
goto cleanup;
}
retval = SDL_GetAudioStreamData(stream, buffer_3, length_3);
if (!SDLTest_AssertCheck(retval == length_3, "Expected SDL_GetAudioStreamData to return %i, got %i", length_3, retval)) {
goto cleanup;
}
retval = SDL_GetAudioStreamAvailable(stream);
if (!SDLTest_AssertCheck(retval == 0, "Expected SDL_GetAudioStreamAvailable to return 0")) {
goto cleanup;
}
for (i = 0; i < frames_3; ++i) {
const float output = buffer_3[i];
const float target = (float) sine_wave_sample(i, spec3.freq, sine_freq, 0.0f);
const double error = SDL_fabs(target - output);
max_error = SDL_max(max_error, error);
sum_squared_error += error * error;
sum_squared_value += target * target;
}
signal_to_noise = 10 * SDL_log10(sum_squared_value / sum_squared_error); /* decibel */
SDLTest_AssertCheck(isfinite(sum_squared_value), "Sum of squared target should be finite.");
SDLTest_AssertCheck(isfinite(sum_squared_error), "Sum of squared error should be finite.");
/* Infinity is theoretically possible when there is very little to no noise */
SDLTest_AssertCheck(!isnan(signal_to_noise), "Signal-to-noise ratio should not be NaN.");
SDLTest_AssertCheck(isfinite(max_error), "Maximum conversion error should be finite.");
SDLTest_AssertCheck(signal_to_noise >= target_signal_to_noise, "Conversion signal-to-noise ratio %f dB should be no less than %f dB.",
signal_to_noise, target_signal_to_noise);
SDLTest_AssertCheck(max_error <= target_max_error, "Maximum conversion error %f should be no more than %f.",
max_error, target_max_error);
status = TEST_COMPLETED;
cleanup:
SDL_free(buffer_1);
SDL_free(buffer_2);
SDL_free(buffer_3);
SDL_DestroyAudioStream(stream);
return status;
}
/* ================= Test Case References ================== */
/* Audio test cases */
@ -952,12 +1281,8 @@ static const SDLTest_TestCaseReference audioTest9 = {
audio_lockUnlockOpenAudioDevice, "audio_lockUnlockOpenAudioDevice", "Locks and unlocks an open audio device.", TEST_ENABLED
};
/* TODO: enable test when SDL_ConvertAudio segfaults on cygwin have been fixed.
* TODO: re-check, since this was changer to AudioStream */
/* For debugging, test case can be run manually using --filter audio_convertAudio */
static const SDLTest_TestCaseReference audioTest10 = {
audio_convertAudio, "audio_convertAudio", "Convert audio using available formats.", TEST_DISABLED
audio_convertAudio, "audio_convertAudio", "Convert audio using available formats.", TEST_ENABLED
};
/* TODO: enable test when SDL_AudioDeviceConnected has been implemented. */
@ -986,11 +1311,20 @@ static const SDLTest_TestCaseReference audioTest16 = {
audio_resampleLoss, "audio_resampleLoss", "Check signal-to-noise ratio and maximum error of audio resampling.", TEST_ENABLED
};
static const SDLTest_TestCaseReference audioTest17 = {
audio_convertAccuracy, "audio_convertAccuracy", "Check accuracy converting between audio formats.", TEST_ENABLED
};
static const SDLTest_TestCaseReference audioTest18 = {
audio_formatChange, "audio_formatChange", "Check handling of format changes.", TEST_ENABLED
};
/* Sequence of Audio test cases */
static const SDLTest_TestCaseReference *audioTests[] = {
&audioTest1, &audioTest2, &audioTest3, &audioTest4, &audioTest5, &audioTest6,
&audioTest7, &audioTest8, &audioTest9, &audioTest10, &audioTest11,
&audioTest12, &audioTest13, &audioTest14, &audioTest15, &audioTest16, NULL
&audioTest12, &audioTest13, &audioTest14, &audioTest15, &audioTest16,
&audioTest17, &audioTest18, NULL
};
/* Audio test suite (global) */

View File

@ -122,7 +122,7 @@ static int pixels_allocFreeFormat(void *arg)
/* Blank/unknown format */
format = 0;
SDLTest_Log("RGB Format: %s (%" SDL_PRIu32 ")", unknownFormat, format);
SDLTest_Log("Pixel Format: %s (%" SDL_PRIu32 ")", unknownFormat, format);
/* Allocate format */
result = SDL_CreatePixelFormat(format);
@ -143,7 +143,7 @@ static int pixels_allocFreeFormat(void *arg)
/* RGB formats */
for (i = 0; i < g_numAllFormats; i++) {
format = g_AllFormats[i];
SDLTest_Log("RGB Format: %s (%" SDL_PRIu32 ")", g_AllFormatsVerbose[i], format);
SDLTest_Log("Pixel Format: %s (%" SDL_PRIu32 ")", g_AllFormatsVerbose[i], format);
/* Allocate format */
result = SDL_CreatePixelFormat(format);
@ -151,11 +151,13 @@ static int pixels_allocFreeFormat(void *arg)
SDLTest_AssertCheck(result != NULL, "Verify result is not NULL");
if (result != NULL) {
SDLTest_AssertCheck(result->format == format, "Verify value of result.format; expected: %" SDL_PRIu32 ", got %" SDL_PRIu32, format, result->format);
SDLTest_AssertCheck(result->BitsPerPixel > 0, "Verify value of result.BitsPerPixel; expected: >0, got %u", result->BitsPerPixel);
SDLTest_AssertCheck(result->BytesPerPixel > 0, "Verify value of result.BytesPerPixel; expected: >0, got %u", result->BytesPerPixel);
if (result->palette != NULL && !SDL_ISPIXELFORMAT_FOURCC(result->format)) {
masks = result->Rmask | result->Gmask | result->Bmask | result->Amask;
SDLTest_AssertCheck(masks > 0, "Verify value of result.[RGBA]mask combined; expected: >0, got %" SDL_PRIu32, masks);
if (!SDL_ISPIXELFORMAT_FOURCC(format)) {
SDLTest_AssertCheck(result->BitsPerPixel > 0, "Verify value of result.BitsPerPixel; expected: >0, got %u", result->BitsPerPixel);
SDLTest_AssertCheck(result->BytesPerPixel > 0, "Verify value of result.BytesPerPixel; expected: >0, got %u", result->BytesPerPixel);
if (!SDL_ISPIXELFORMAT_INDEXED(format)) {
masks = result->Rmask | result->Gmask | result->Bmask | result->Amask;
SDLTest_AssertCheck(masks > 0, "Verify value of result.[RGBA]mask combined; expected: >0, got %" SDL_PRIu32, masks);
}
}
/* Deallocate again */

View File

@ -2008,15 +2008,22 @@ int main(int argc, char *argv[])
HandleGamepadRemoved(controllers[0].id);
DelController(controllers[0].id);
}
SDL_free(controllers);
SDL_free(controller_name);
DestroyGamepadImage(image);
DestroyGamepadDisplay(gamepad_elements);
DestroyGamepadTypeDisplay(gamepad_type);
DestroyJoystickDisplay(joystick_elements);
DestroyGamepadButton(setup_mapping_button);
DestroyGamepadButton(done_mapping_button);
DestroyGamepadButton(cancel_button);
DestroyGamepadButton(clear_button);
DestroyGamepadButton(copy_button);
DestroyGamepadButton(paste_button);
SDLTest_CleanupTextDrawing();
SDL_DestroyRenderer(screen);
SDL_DestroyWindow(window);
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD);
SDL_Quit();
SDLTest_CommonDestroyState(state);
return 0;
}

View File

@ -10,24 +10,11 @@
freely.
*/
#include <stdlib.h>
#include <SDL3/SDL_test_common.h>
#include <SDL3/SDL_main.h>
static SDLTest_CommonState *state;
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void
quit(int rc)
{
SDLTest_CommonQuit(state);
/* Let 'main()' return normally */
if (rc != 0) {
exit(rc);
}
}
int main(int argc, char *argv[])
{
int i, done;
@ -35,6 +22,7 @@ int main(int argc, char *argv[])
SDL_bool is_hover = SDL_FALSE;
float x = 0.0f, y = 0.0f;
unsigned int windowID = 0;
int return_code = -1;
/* Initialize test framework */
state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
@ -58,12 +46,14 @@ int main(int argc, char *argv[])
}
if (consumed < 0) {
SDLTest_CommonLogUsage(state, argv[0], NULL);
quit(1);
return_code = 1;
goto quit;
}
i += consumed;
}
if (!SDLTest_CommonInit(state)) {
quit(2);
return_code = 1;
goto quit;
}
@ -114,7 +104,8 @@ int main(int argc, char *argv[])
SDL_Delay(16);
}
quit(0);
/* keep the compiler happy ... */
return 0;
return_code = 0;
quit:
SDLTest_CommonQuit(state);
return return_code;
}

View File

@ -369,6 +369,7 @@ int main(int argc, char *argv[])
SDL_RWclose(rwops);
SDL_Log("test5 OK\n");
cleanup();
SDL_Quit();
SDLTest_CommonDestroyState(state);
return 0; /* all ok */
}

View File

@ -0,0 +1,33 @@
/*
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely.
*/
/* Call SDL_GetPrefPath to warm the SHGetFolderPathW cache */
/**
* We noticed frequent ci timeouts running testfilesystem on 32-bit Windows.
* Internally, this functions calls Shell32.SHGetFolderPathW.
*/
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
int main(int argc, char *argv[])
{
Uint64 start;
(void)argc;
(void)argv;
SDL_Init(0);
start = SDL_GetTicks();
SDL_GetPrefPath("libsdl", "test_filesystem");
SDL_Log("SDL_GetPrefPath took %" SDL_PRIu64 "ms", SDL_GetTicks() - start);
SDL_Quit();
return 0;
}

View File

@ -28,7 +28,6 @@ static Uint8 *sound = NULL; /* Pointer to wave data */
static Uint32 soundlen = 0; /* Length of wave data */
/* these have to be in globals so the Emscripten port can see them in the mainloop. :/ */
static SDL_AudioDeviceID device = 0;
static SDL_AudioStream *stream = NULL;
@ -37,7 +36,6 @@ static void loop(void)
{
if (SDL_GetAudioStreamAvailable(stream) == 0) {
SDL_Log("done.");
SDL_CloseAudioDevice(device);
SDL_DestroyAudioStream(stream);
SDL_free(sound);
SDL_Quit();
@ -65,13 +63,10 @@ test_multi_audio(SDL_AudioDeviceID *devices, int devcount)
SDL_Log("Playing on device #%d of %d: id=%u, name='%s'...", i, devcount, (unsigned int) devices[i], devname);
device = SDL_OpenAudioDevice(devices[i], &spec);
if (device == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Open device failed: %s", SDL_GetError());
} else if ((stream = SDL_CreateAndBindAudioStream(device, &spec)) == NULL) { /* we can reuse these, but we'll just make one each time for now. */
if ((stream = SDL_OpenAudioDeviceStream(devices[i], &spec, NULL, NULL)) == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Audio stream creation failed: %s", SDL_GetError());
SDL_CloseAudioDevice(device);
} else {
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream));
SDL_PutAudioStreamData(stream, sound, soundlen);
SDL_FlushAudioStream(stream);
#ifdef __EMSCRIPTEN__
@ -87,7 +82,6 @@ test_multi_audio(SDL_AudioDeviceID *devices, int devcount)
}
#endif
SDL_Log("done.");
SDL_CloseAudioDevice(device);
SDL_DestroyAudioStream(stream);
}
SDL_free(devname);
@ -101,29 +95,19 @@ test_multi_audio(SDL_AudioDeviceID *devices, int devcount)
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!");
} else {
for (i = 0; i < devcount; i++) {
char *devname = SDL_GetAudioDeviceName(devices[i]);
device = SDL_OpenAudioDevice(devices[i], &spec);
if (device == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Open device %d of %d (id=%u, name='%s') failed: %s\n", i, devcount, (unsigned int) devices[i], devname, SDL_GetError());
}
SDL_free(devname);
devices[i] = device; /* just replace the physical device ID with the newly-opened logical device ID. */
if (device) {
SDL_PauseAudioDevice(device); /* hold while we set up all the streams. */
streams[i] = SDL_CreateAndBindAudioStream(device, &spec);
if (streams[i] == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Audio stream creation failed for device %d of %d: %s", i, devcount, SDL_GetError());
} else {
SDL_PutAudioStreamData(streams[i], sound, soundlen);
SDL_FlushAudioStream(streams[i]);
}
streams[i] = SDL_OpenAudioDeviceStream(devices[i], &spec, NULL, NULL);
if (streams[i] == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Audio stream creation failed for device %d of %d: %s", i, devcount, SDL_GetError());
} else {
SDL_PutAudioStreamData(streams[i], sound, soundlen);
SDL_FlushAudioStream(streams[i]);
}
}
/* try to start all the devices about the same time. SDL does not guarantee sync across physical devices. */
for (i = 0; i < devcount; i++) {
if (devices[i]) {
SDL_ResumeAudioDevice(devices[i]);
if (streams[i]) {
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(streams[i]));
}
}
@ -143,7 +127,6 @@ test_multi_audio(SDL_AudioDeviceID *devices, int devcount)
}
for (i = 0; i < devcount; i++) {
SDL_CloseAudioDevice(devices[i]);
SDL_DestroyAudioStream(streams[i]);
}

View File

@ -212,6 +212,12 @@ int main(int argc, char *argv[])
MoveSprites(renderer, sprite);
}
SDL_DestroyTexture(sprite);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_free(positions);
SDL_free(velocities);
quit(0);
return 0; /* to prevent compiler warning */

View File

@ -388,6 +388,15 @@ ret:
/* Destroy the window. */
SDL_DestroyWindow(window);
if (g_bitmap) {
SDL_free(g_bitmap);
g_bitmap = NULL;
}
if (g_shape_surface) {
SDL_DestroySurface(g_shape_surface);
g_shape_surface = NULL;
}
SDL_Quit();
SDLTest_CommonDestroyState(state);

View File

@ -20,7 +20,8 @@
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include "testutils.h"
#include "icon.h"
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
@ -35,15 +36,23 @@ static int sprite_w, sprite_h;
static SDL_Renderer *renderer;
static int done;
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void
quit(int rc)
{
SDL_Quit();
/* Let 'main()' return normally */
if (rc != 0) {
exit(rc);
static SDL_Texture *CreateTexture(SDL_Renderer *r, unsigned char *data, unsigned int len, int *w, int *h) {
SDL_Texture *texture = NULL;
SDL_Surface *surface;
SDL_RWops *src = SDL_RWFromConstMem(data, len);
if (src) {
surface = SDL_LoadBMP_RW(src, SDL_TRUE);
if (surface) {
/* Treat white as transparent */
SDL_SetSurfaceColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 255, 255, 255));
texture = SDL_CreateTextureFromSurface(r, surface);
*w = surface->w;
*h = surface->h;
SDL_DestroySurface(surface);
}
}
return texture;
}
static void MoveSprites(void)
@ -100,7 +109,8 @@ static void loop(void)
int main(int argc, char *argv[])
{
SDL_Window *window;
SDL_Window *window = NULL;
int return_code = -1;
int i;
/* Enable standard application logging */
@ -108,17 +118,25 @@ int main(int argc, char *argv[])
if (argc > 1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "USAGE: %s\n", argv[0]);
quit(1);
return_code = 1;
goto quit;
}
if (SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer) < 0) {
quit(2);
return_code = 2;
goto quit;
}
sprite = LoadTexture(renderer, "icon.bmp", SDL_TRUE, &sprite_w, &sprite_h);
if (SDL_SetWindowTitle(window, argv[0]) < 0) {
SDL_Log("SDL_SetWindowTitle: %s", SDL_GetError());
}
sprite = CreateTexture(renderer, icon_bmp, icon_bmp_len, &sprite_w, &sprite_h);
if (sprite == NULL) {
quit(2);
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture (%s)", SDL_GetError());
return_code = 3;
goto quit;
}
/* Initialize the sprite positions */
@ -146,7 +164,10 @@ int main(int argc, char *argv[])
loop();
}
#endif
quit(0);
return 0; /* to prevent compiler warning */
return_code = 0;
quit:
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return return_code;
}

View File

@ -96,7 +96,7 @@ static SDL_bool is_lfe_channel(int channel_index, int channel_count)
return (channel_count == 3 && channel_index == 2) || (channel_count >= 6 && channel_index == 3);
}
static void SDLCALL fill_buffer(SDL_AudioStream *stream, int len, void *unused)
static void SDLCALL fill_buffer(void *userdata, SDL_AudioStream *stream, int len, int totallen)
{
const int samples = len / sizeof(Sint16);
Sint16 *buffer = NULL;
@ -193,12 +193,11 @@ int main(int argc, char *argv[])
char *devname = SDL_GetAudioDeviceName(devices[i]);
int j;
SDL_AudioSpec spec;
SDL_AudioDeviceID dev;
SDL_Log("Testing audio device: %s\n", devname);
SDL_free(devname);
if (SDL_GetAudioDeviceFormat(devices[i], &spec) != 0) {
if (SDL_GetAudioDeviceFormat(devices[i], &spec, NULL) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GetAudioDeviceFormat() failed: %s\n", SDL_GetError());
continue;
}
@ -206,26 +205,18 @@ int main(int argc, char *argv[])
SDL_Log(" (%d channels)\n", spec.channels);
spec.freq = SAMPLE_RATE_HZ;
spec.format = SDL_AUDIO_S16SYS;
dev = SDL_OpenAudioDevice(devices[i], &spec);
if (dev == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_OpenAudioDevice() failed: %s\n", SDL_GetError());
continue;
}
stream = SDL_CreateAndBindAudioStream(dev, &spec);
if (stream == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateAndBindAudioStream() failed: %s\n", SDL_GetError());
SDL_CloseAudioDevice(dev);
continue;
}
spec.format = SDL_AUDIO_S16;
/* These are used by the fill_buffer callback */
total_channels = spec.channels;
active_channel = 0;
SDL_SetAudioStreamGetCallback(stream, fill_buffer, NULL);
stream = SDL_OpenAudioDeviceStream(devices[i], &spec, fill_buffer, NULL);
if (stream == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_OpenAudioDeviceStream() failed: %s\n", SDL_GetError());
continue;
}
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream));
for (j = 0; j < total_channels; j++) {
const int sine_freq = is_lfe_channel(j, total_channels) ? LFE_SINE_FREQ_HZ : SINE_FREQ_HZ;
@ -240,7 +231,6 @@ int main(int argc, char *argv[])
}
}
SDL_CloseAudioDevice(dev);
SDL_DestroyAudioStream(stream);
}

View File

@ -10,8 +10,6 @@
freely.
*/
#include <stdlib.h>
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#endif
@ -42,17 +40,6 @@ static SDL_Cursor *cursor = NULL;
static SDL_bool relative_mode = SDL_FALSE;
static const SDL_DisplayMode *highlighted_mode = NULL;
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void
quit(int rc)
{
SDLTest_CommonQuit(state);
/* Let 'main()' return normally */
if (rc != 0) {
exit(rc);
}
}
/* Draws the modes menu, and stores the mode index under the mouse in highlighted_mode */
static void
draw_modes_menu(SDL_Window *window, SDL_Renderer *renderer, SDL_FRect viewport)
@ -298,7 +285,7 @@ int main(int argc, char *argv[])
#endif
SDL_DestroyCursor(cursor);
quit(0);
/* keep the compiler happy ... */
SDLTest_CleanupTextDrawing();
SDLTest_CommonQuit(state);
return 0;
}

View File

@ -243,6 +243,7 @@ int main(int argc, char **argv)
char *filename = NULL;
SDL_Surface *original;
SDL_Surface *converted;
SDL_Surface *bmp;
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *output[3];
@ -368,7 +369,9 @@ int main(int argc, char **argv)
}
filename = GetResourceFilename(filename, "testyuv.bmp");
original = SDL_ConvertSurfaceFormat(SDL_LoadBMP(filename), SDL_PIXELFORMAT_RGB24);
bmp = SDL_LoadBMP(filename);
original = SDL_ConvertSurfaceFormat(bmp, SDL_PIXELFORMAT_RGB24);
SDL_DestroySurface(bmp);
if (original == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError());
return 3;
@ -481,7 +484,13 @@ int main(int argc, char **argv)
SDL_Delay(10);
}
}
SDL_free(raw_yuv);
SDL_free(filename);
SDL_DestroySurface(original);
SDL_DestroySurface(converted);
SDLTest_CleanupTextDrawing();
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
SDLTest_CommonDestroyState(state);
return 0;