test/testaudiocapture.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 01 Aug 2016 00:18:56 -0400
changeset 10231 4b0893d63092
child 10237 0d344873cd93
permissions -rw-r--r--
audio: Initial bits to enable audio capture support.
icculus@10231
     1
/*
icculus@10231
     2
  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
icculus@10231
     3
icculus@10231
     4
  This software is provided 'as-is', without any express or implied
icculus@10231
     5
  warranty.  In no event will the authors be held liable for any damages
icculus@10231
     6
  arising from the use of this software.
icculus@10231
     7
icculus@10231
     8
  Permission is granted to anyone to use this software for any purpose,
icculus@10231
     9
  including commercial applications, and to alter it and redistribute it
icculus@10231
    10
  freely.
icculus@10231
    11
*/
icculus@10231
    12
#include "SDL.h"
icculus@10231
    13
icculus@10231
    14
#ifdef __EMSCRIPTEN__
icculus@10231
    15
#include <emscripten/emscripten.h>
icculus@10231
    16
#endif
icculus@10231
    17
icculus@10231
    18
#define CAPTURE_SECONDS 5
icculus@10231
    19
icculus@10231
    20
static SDL_AudioSpec spec;
icculus@10231
    21
static Uint8 *sound = NULL;     /* Pointer to wave data */
icculus@10231
    22
static Uint32 soundlen = 0;     /* Length of wave data */
icculus@10231
    23
static Uint32 processed = 0;
icculus@10231
    24
static SDL_AudioDeviceID devid = 0;
icculus@10231
    25
icculus@10231
    26
void SDLCALL
icculus@10231
    27
capture_callback(void *arg, Uint8 * stream, int len)
icculus@10231
    28
{
icculus@10231
    29
    const int avail = (int) (soundlen - processed);
icculus@10231
    30
    if (len > avail) {
icculus@10231
    31
        len = avail;
icculus@10231
    32
    }
icculus@10231
    33
icculus@10231
    34
    /*SDL_Log("CAPTURE CALLBACK: %d more bytes\n", len);*/
icculus@10231
    35
    SDL_memcpy(sound + processed, stream, len);
icculus@10231
    36
    processed += len;
icculus@10231
    37
}
icculus@10231
    38
icculus@10231
    39
void SDLCALL
icculus@10231
    40
play_callback(void *arg, Uint8 * stream, int len)
icculus@10231
    41
{
icculus@10231
    42
    const Uint8 *waveptr = sound + processed;
icculus@10231
    43
    const int avail = soundlen - processed;
icculus@10231
    44
    int cpy = len;
icculus@10231
    45
    if (cpy > avail) {
icculus@10231
    46
        cpy = avail;
icculus@10231
    47
    }
icculus@10231
    48
icculus@10231
    49
    /*SDL_Log("PLAY CALLBACK: %d more bytes\n", cpy);*/
icculus@10231
    50
    SDL_memcpy(stream, waveptr, cpy);
icculus@10231
    51
    processed += cpy;
icculus@10231
    52
icculus@10231
    53
    len -= cpy;
icculus@10231
    54
    if (len > 0) {
icculus@10231
    55
        SDL_memset(stream + cpy, spec.silence, len);
icculus@10231
    56
    }
icculus@10231
    57
}
icculus@10231
    58
icculus@10231
    59
static void
icculus@10231
    60
loop()
icculus@10231
    61
{
icculus@10231
    62
    SDL_Event e;
icculus@10231
    63
    SDL_bool please_quit = SDL_FALSE;
icculus@10231
    64
icculus@10231
    65
    while (SDL_PollEvent(&e)) {
icculus@10231
    66
        if (e.type == SDL_QUIT) {
icculus@10231
    67
            please_quit = SDL_TRUE;
icculus@10231
    68
        }
icculus@10231
    69
    }
icculus@10231
    70
icculus@10231
    71
    if ((!please_quit) && (processed >= soundlen)) {
icculus@10231
    72
        processed = 0;
icculus@10231
    73
        if (spec.callback == capture_callback) {
icculus@10231
    74
            SDL_Log("Done recording, playing back...\n");
icculus@10231
    75
            SDL_PauseAudioDevice(devid, 1);
icculus@10231
    76
            SDL_CloseAudioDevice(devid);
icculus@10231
    77
icculus@10231
    78
            spec.callback = play_callback;
icculus@10231
    79
            devid = SDL_OpenAudioDevice(NULL, 0, &spec, &spec, 0);
icculus@10231
    80
            if (!devid) {
icculus@10231
    81
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for playback!\n");
icculus@10231
    82
                SDL_Quit();
icculus@10231
    83
                exit(1);
icculus@10231
    84
            }
icculus@10231
    85
icculus@10231
    86
            SDL_PauseAudioDevice(devid, 0);
icculus@10231
    87
        } else {
icculus@10231
    88
            SDL_Log("Done playing back.\n");
icculus@10231
    89
            please_quit = SDL_TRUE;
icculus@10231
    90
        }
icculus@10231
    91
    }
icculus@10231
    92
icculus@10231
    93
    if (please_quit) {
icculus@10231
    94
        /* stop playing back, quit. */
icculus@10231
    95
        SDL_Log("Shutting down.\n");
icculus@10231
    96
        SDL_PauseAudioDevice(devid, 1);
icculus@10231
    97
        SDL_CloseAudioDevice(devid);
icculus@10231
    98
        SDL_free(sound);
icculus@10231
    99
        sound = NULL;
icculus@10231
   100
        SDL_Quit();
icculus@10231
   101
        #ifdef __EMSCRIPTEN__
icculus@10231
   102
        emscripten_cancel_main_loop();
icculus@10231
   103
        #endif
icculus@10231
   104
        exit(0);
icculus@10231
   105
    }
icculus@10231
   106
}
icculus@10231
   107
icculus@10231
   108
int
icculus@10231
   109
main(int argc, char **argv)
icculus@10231
   110
{
icculus@10231
   111
    /* Enable standard application logging */
icculus@10231
   112
    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
icculus@10231
   113
icculus@10231
   114
    /* Load the SDL library */
icculus@10231
   115
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
icculus@10231
   116
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
icculus@10231
   117
        return (1);
icculus@10231
   118
    }
icculus@10231
   119
icculus@10231
   120
    /* Android apparently needs a window...? */
icculus@10231
   121
    #ifdef __ANDROID__  
icculus@10231
   122
    SDL_CreateWindow("testaudiocapture", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 240, 0);
icculus@10231
   123
    #endif
icculus@10231
   124
icculus@10231
   125
    SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
icculus@10231
   126
icculus@10231
   127
    SDL_zero(spec);
icculus@10231
   128
    spec.freq = 44100;
icculus@10231
   129
    spec.format = AUDIO_F32SYS;
icculus@10231
   130
    spec.channels = 1;
icculus@10231
   131
    spec.samples = 1024;
icculus@10231
   132
    spec.callback = capture_callback;
icculus@10231
   133
icculus@10231
   134
    soundlen = spec.freq * (SDL_AUDIO_BITSIZE(spec.format) / 8) * spec.channels * CAPTURE_SECONDS;
icculus@10231
   135
    sound = (Uint8 *) SDL_malloc(soundlen);
icculus@10231
   136
    if (!sound) {
icculus@10231
   137
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory\n");
icculus@10231
   138
        SDL_Quit();
icculus@10231
   139
        return 1;
icculus@10231
   140
    }
icculus@10231
   141
icculus@10231
   142
    devid = SDL_OpenAudioDevice(NULL, 1, &spec, &spec, 0);
icculus@10231
   143
    if (!devid) {
icculus@10231
   144
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for capture: %s!\n", SDL_GetError());
icculus@10231
   145
        SDL_free(sound);
icculus@10231
   146
        SDL_Quit();
icculus@10231
   147
        exit(1);
icculus@10231
   148
    }
icculus@10231
   149
icculus@10231
   150
    SDL_Log("Recording for %d seconds...\n", CAPTURE_SECONDS);
icculus@10231
   151
    SDL_PauseAudioDevice(devid, 0);
icculus@10231
   152
icculus@10231
   153
#ifdef __EMSCRIPTEN__
icculus@10231
   154
    emscripten_set_main_loop(loop, 0, 1);
icculus@10231
   155
#else
icculus@10231
   156
    while (1) { loop(); SDL_Delay(16); }
icculus@10231
   157
#endif
icculus@10231
   158
icculus@10231
   159
    return 0;
icculus@10231
   160
}
icculus@10231
   161