123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- /*
- Copyright (C) 1997-2025 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.
- */
- #define SDL_MAIN_USE_CALLBACKS 1
- #include <SDL3/SDL.h>
- #include <SDL3/SDL_main.h>
- #include <SDL3/SDL_test.h>
- static SDL_Window *window = NULL;
- static SDL_Renderer *renderer = NULL;
- static SDL_AudioStream *stream_in = NULL;
- static SDL_AudioStream *stream_out = NULL;
- static SDLTest_CommonState *state = NULL;
- SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv)
- {
- SDL_AudioDeviceID *devices;
- SDL_AudioSpec outspec;
- SDL_AudioSpec inspec;
- SDL_AudioDeviceID device;
- SDL_AudioDeviceID want_device = SDL_AUDIO_DEVICE_DEFAULT_RECORDING;
- const char *devname = NULL;
- int i;
- /* this doesn't have to run very much, so give up tons of CPU time between iterations. */
- SDL_SetHint(SDL_HINT_MAIN_CALLBACK_RATE, "15");
- /* Initialize test framework */
- state = SDLTest_CommonCreateState(argv, 0);
- if (!state) {
- return SDL_APP_SUCCESS;
- }
- /* Parse commandline */
- for (i = 1; i < argc;) {
- int consumed;
- consumed = SDLTest_CommonArg(state, i);
- if (!consumed) {
- if (!devname) {
- devname = argv[i];
- consumed = 1;
- }
- }
- if (consumed <= 0) {
- static const char *options[] = { "[device_name]", NULL };
- SDLTest_CommonLogUsage(state, argv[0], options);
- return SDL_APP_FAILURE;
- }
- i += consumed;
- }
- /* Load the SDL library */
- if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError());
- return SDL_APP_SUCCESS;
- }
- if (!SDL_CreateWindowAndRenderer("testaudiorecording", 320, 240, 0, &window, &renderer)) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create SDL window and renderer: %s", SDL_GetError());
- return SDL_APP_SUCCESS;
- }
- SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
- SDL_RenderClear(renderer);
- SDL_RenderPresent(renderer);
- SDL_Log("Using audio driver: %s", SDL_GetCurrentAudioDriver());
- devices = SDL_GetAudioRecordingDevices(NULL);
- for (i = 0; devices[i] != 0; i++) {
- const char *name = SDL_GetAudioDeviceName(devices[i]);
- SDL_Log(" Recording device #%d: '%s'", i, name);
- if (devname && (SDL_strcmp(devname, name) == 0)) {
- want_device = devices[i];
- }
- }
- if (devname && (want_device == SDL_AUDIO_DEVICE_DEFAULT_RECORDING)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Didn't see a recording device named '%s', using the system default instead.", devname);
- devname = NULL;
- }
- /* DirectSound can fail in some instances if you open the same hardware
- for both recording and output and didn't open the output end first,
- according to the docs, so if you're doing something like this, always
- open your recording devices second in case you land in those bizarre
- circumstances. */
- SDL_Log("Opening default playback device...");
- device = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL);
- if (!device) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for playback: %s!", SDL_GetError());
- SDL_free(devices);
- return SDL_APP_FAILURE;
- }
- SDL_PauseAudioDevice(device);
- 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!", SDL_GetError());
- SDL_free(devices);
- return SDL_APP_FAILURE;
- } else if (!SDL_BindAudioStream(device, stream_out)) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't bind an audio stream for playback: %s!", SDL_GetError());
- SDL_free(devices);
- return SDL_APP_FAILURE;
- }
- SDL_Log("Opening recording device %s%s%s...",
- devname ? "'" : "",
- devname ? devname : "[[default]]",
- devname ? "'" : "");
- device = SDL_OpenAudioDevice(want_device, NULL);
- if (!device) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for recording: %s!", SDL_GetError());
- SDL_free(devices);
- return SDL_APP_FAILURE;
- }
- SDL_free(devices);
- SDL_PauseAudioDevice(device);
- 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 recording: %s!", SDL_GetError());
- return SDL_APP_FAILURE;
- } else if (!SDL_BindAudioStream(device, stream_in)) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't bind an audio stream for recording: %s!", SDL_GetError());
- return SDL_APP_FAILURE;
- }
- SDL_SetAudioStreamFormat(stream_in, NULL, &outspec); /* make sure we output at the playback format. */
- SDL_Log("Ready! Hold down mouse or finger to record!");
- return SDL_APP_CONTINUE;
- }
- SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
- {
- if (event->type == SDL_EVENT_QUIT) {
- return SDL_APP_SUCCESS;
- } else if (event->type == SDL_EVENT_KEY_DOWN) {
- if (event->key.key == SDLK_ESCAPE) {
- return SDL_APP_SUCCESS;
- }
- } else if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
- if (event->button.button == 1) {
- SDL_PauseAudioStreamDevice(stream_out);
- SDL_FlushAudioStream(stream_out); /* so no samples are held back for resampling purposes. */
- SDL_ResumeAudioStreamDevice(stream_in);
- }
- } else if (event->type == SDL_EVENT_MOUSE_BUTTON_UP) {
- if (event->button.button == 1) {
- SDL_PauseAudioStreamDevice(stream_in);
- SDL_FlushAudioStream(stream_in); /* so no samples are held back for resampling purposes. */
- SDL_ResumeAudioStreamDevice(stream_out);
- }
- }
- return SDL_APP_CONTINUE;
- }
- SDL_AppResult SDL_AppIterate(void *appstate)
- {
- if (!SDL_AudioStreamDevicePaused(stream_in)) {
- SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
- } else {
- SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
- }
- SDL_RenderClear(renderer);
- SDL_RenderPresent(renderer);
- /* Feed any new data we recorded to the output stream. It'll play when we unpause the device. */
- while (SDL_GetAudioStreamAvailable(stream_in) > 0) {
- Uint8 buf[1024];
- const int br = SDL_GetAudioStreamData(stream_in, buf, sizeof(buf));
- if (br < 0) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to read from input audio stream: %s", SDL_GetError());
- return SDL_APP_FAILURE;
- } else if (!SDL_PutAudioStreamData(stream_out, buf, br)) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to write to output audio stream: %s", SDL_GetError());
- return SDL_APP_FAILURE;
- }
- }
- return SDL_APP_CONTINUE;
- }
- void SDL_AppQuit(void *appstate, SDL_AppResult result)
- {
- SDL_Log("Shutting down.");
- const SDL_AudioDeviceID devid_in = SDL_GetAudioStreamDevice(stream_in);
- const SDL_AudioDeviceID devid_out = SDL_GetAudioStreamDevice(stream_out);
- SDL_CloseAudioDevice(devid_in); /* !!! FIXME: use SDL_OpenAudioDeviceStream instead so we can dump this. */
- SDL_CloseAudioDevice(devid_out);
- SDL_DestroyAudioStream(stream_in);
- SDL_DestroyAudioStream(stream_out);
- SDL_DestroyRenderer(renderer);
- SDL_DestroyWindow(window);
- SDL_Quit();
- SDLTest_CommonDestroyState(state);
- }
|