audio: Initial bits to enable audio capture support.
authorRyan C. Gordon <icculus@icculus.org>
Mon, 01 Aug 2016 00:18:56 -0400
changeset 102314b0893d63092
parent 10212 af95dd343a25
child 10232 4f29bb9e19c3
audio: Initial bits to enable audio capture support.
.hgignore
src/audio/SDL_audio.c
test/Makefile.in
test/testaudiocapture.c
     1.1 --- a/.hgignore	Wed Jul 27 20:47:31 2016 +0200
     1.2 +++ b/.hgignore	Mon Aug 01 00:18:56 2016 -0400
     1.3 @@ -120,6 +120,7 @@
     1.4  test/torturethread
     1.5  test/testdisplayinfo
     1.6  test/testqsort
     1.7 +test/testaudiocapture
     1.8  test/*.exe
     1.9  test/*.dSYM
    1.10  buildbot
     2.1 --- a/src/audio/SDL_audio.c	Wed Jul 27 20:47:31 2016 +0200
     2.2 +++ b/src/audio/SDL_audio.c	Mon Aug 01 00:18:56 2016 -0400
     2.3 @@ -317,7 +317,7 @@
     2.4  static SDL_INLINE int
     2.5  add_capture_device(const char *name, void *handle)
     2.6  {
     2.7 -    /* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/
     2.8 +    SDL_assert(current_audio.impl.HasCaptureSupport);
     2.9      return add_audio_device(name, handle, &current_audio.inputDevices, &current_audio.inputDeviceCount);
    2.10  }
    2.11  
     3.1 --- a/test/Makefile.in	Wed Jul 27 20:47:31 2016 +0200
     3.2 +++ b/test/Makefile.in	Mon Aug 01 00:18:56 2016 -0400
     3.3 @@ -13,6 +13,7 @@
     3.4  	loopwavequeue$(EXE) \
     3.5  	testatomic$(EXE) \
     3.6  	testaudioinfo$(EXE) \
     3.7 +	testaudiocapture$(EXE) \
     3.8  	testautomation$(EXE) \
     3.9  	testbounds$(EXE) \
    3.10  	testcustomcursor$(EXE) \
    3.11 @@ -113,6 +114,9 @@
    3.12  testaudiohotplug$(EXE): $(srcdir)/testaudiohotplug.c
    3.13  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
    3.14  
    3.15 +testaudiocapture$(EXE): $(srcdir)/testaudiocapture.c
    3.16 +	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
    3.17 +
    3.18  testatomic$(EXE): $(srcdir)/testatomic.c
    3.19  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
    3.20  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/test/testaudiocapture.c	Mon Aug 01 00:18:56 2016 -0400
     4.3 @@ -0,0 +1,161 @@
     4.4 +/*
     4.5 +  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
     4.6 +
     4.7 +  This software is provided 'as-is', without any express or implied
     4.8 +  warranty.  In no event will the authors be held liable for any damages
     4.9 +  arising from the use of this software.
    4.10 +
    4.11 +  Permission is granted to anyone to use this software for any purpose,
    4.12 +  including commercial applications, and to alter it and redistribute it
    4.13 +  freely.
    4.14 +*/
    4.15 +#include "SDL.h"
    4.16 +
    4.17 +#ifdef __EMSCRIPTEN__
    4.18 +#include <emscripten/emscripten.h>
    4.19 +#endif
    4.20 +
    4.21 +#define CAPTURE_SECONDS 5
    4.22 +
    4.23 +static SDL_AudioSpec spec;
    4.24 +static Uint8 *sound = NULL;     /* Pointer to wave data */
    4.25 +static Uint32 soundlen = 0;     /* Length of wave data */
    4.26 +static Uint32 processed = 0;
    4.27 +static SDL_AudioDeviceID devid = 0;
    4.28 +
    4.29 +void SDLCALL
    4.30 +capture_callback(void *arg, Uint8 * stream, int len)
    4.31 +{
    4.32 +    const int avail = (int) (soundlen - processed);
    4.33 +    if (len > avail) {
    4.34 +        len = avail;
    4.35 +    }
    4.36 +
    4.37 +    /*SDL_Log("CAPTURE CALLBACK: %d more bytes\n", len);*/
    4.38 +    SDL_memcpy(sound + processed, stream, len);
    4.39 +    processed += len;
    4.40 +}
    4.41 +
    4.42 +void SDLCALL
    4.43 +play_callback(void *arg, Uint8 * stream, int len)
    4.44 +{
    4.45 +    const Uint8 *waveptr = sound + processed;
    4.46 +    const int avail = soundlen - processed;
    4.47 +    int cpy = len;
    4.48 +    if (cpy > avail) {
    4.49 +        cpy = avail;
    4.50 +    }
    4.51 +
    4.52 +    /*SDL_Log("PLAY CALLBACK: %d more bytes\n", cpy);*/
    4.53 +    SDL_memcpy(stream, waveptr, cpy);
    4.54 +    processed += cpy;
    4.55 +
    4.56 +    len -= cpy;
    4.57 +    if (len > 0) {
    4.58 +        SDL_memset(stream + cpy, spec.silence, len);
    4.59 +    }
    4.60 +}
    4.61 +
    4.62 +static void
    4.63 +loop()
    4.64 +{
    4.65 +    SDL_Event e;
    4.66 +    SDL_bool please_quit = SDL_FALSE;
    4.67 +
    4.68 +    while (SDL_PollEvent(&e)) {
    4.69 +        if (e.type == SDL_QUIT) {
    4.70 +            please_quit = SDL_TRUE;
    4.71 +        }
    4.72 +    }
    4.73 +
    4.74 +    if ((!please_quit) && (processed >= soundlen)) {
    4.75 +        processed = 0;
    4.76 +        if (spec.callback == capture_callback) {
    4.77 +            SDL_Log("Done recording, playing back...\n");
    4.78 +            SDL_PauseAudioDevice(devid, 1);
    4.79 +            SDL_CloseAudioDevice(devid);
    4.80 +
    4.81 +            spec.callback = play_callback;
    4.82 +            devid = SDL_OpenAudioDevice(NULL, 0, &spec, &spec, 0);
    4.83 +            if (!devid) {
    4.84 +                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for playback!\n");
    4.85 +                SDL_Quit();
    4.86 +                exit(1);
    4.87 +            }
    4.88 +
    4.89 +            SDL_PauseAudioDevice(devid, 0);
    4.90 +        } else {
    4.91 +            SDL_Log("Done playing back.\n");
    4.92 +            please_quit = SDL_TRUE;
    4.93 +        }
    4.94 +    }
    4.95 +
    4.96 +    if (please_quit) {
    4.97 +        /* stop playing back, quit. */
    4.98 +        SDL_Log("Shutting down.\n");
    4.99 +        SDL_PauseAudioDevice(devid, 1);
   4.100 +        SDL_CloseAudioDevice(devid);
   4.101 +        SDL_free(sound);
   4.102 +        sound = NULL;
   4.103 +        SDL_Quit();
   4.104 +        #ifdef __EMSCRIPTEN__
   4.105 +        emscripten_cancel_main_loop();
   4.106 +        #endif
   4.107 +        exit(0);
   4.108 +    }
   4.109 +}
   4.110 +
   4.111 +int
   4.112 +main(int argc, char **argv)
   4.113 +{
   4.114 +    /* Enable standard application logging */
   4.115 +    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   4.116 +
   4.117 +    /* Load the SDL library */
   4.118 +    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
   4.119 +        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
   4.120 +        return (1);
   4.121 +    }
   4.122 +
   4.123 +    /* Android apparently needs a window...? */
   4.124 +    #ifdef __ANDROID__  
   4.125 +    SDL_CreateWindow("testaudiocapture", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 240, 0);
   4.126 +    #endif
   4.127 +
   4.128 +    SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
   4.129 +
   4.130 +    SDL_zero(spec);
   4.131 +    spec.freq = 44100;
   4.132 +    spec.format = AUDIO_F32SYS;
   4.133 +    spec.channels = 1;
   4.134 +    spec.samples = 1024;
   4.135 +    spec.callback = capture_callback;
   4.136 +
   4.137 +    soundlen = spec.freq * (SDL_AUDIO_BITSIZE(spec.format) / 8) * spec.channels * CAPTURE_SECONDS;
   4.138 +    sound = (Uint8 *) SDL_malloc(soundlen);
   4.139 +    if (!sound) {
   4.140 +        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory\n");
   4.141 +        SDL_Quit();
   4.142 +        return 1;
   4.143 +    }
   4.144 +
   4.145 +    devid = SDL_OpenAudioDevice(NULL, 1, &spec, &spec, 0);
   4.146 +    if (!devid) {
   4.147 +        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for capture: %s!\n", SDL_GetError());
   4.148 +        SDL_free(sound);
   4.149 +        SDL_Quit();
   4.150 +        exit(1);
   4.151 +    }
   4.152 +
   4.153 +    SDL_Log("Recording for %d seconds...\n", CAPTURE_SECONDS);
   4.154 +    SDL_PauseAudioDevice(devid, 0);
   4.155 +
   4.156 +#ifdef __EMSCRIPTEN__
   4.157 +    emscripten_set_main_loop(loop, 0, 1);
   4.158 +#else
   4.159 +    while (1) { loop(); SDL_Delay(16); }
   4.160 +#endif
   4.161 +
   4.162 +    return 0;
   4.163 +}
   4.164 +