test/loopbackaudio.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 15 Mar 2017 11:39:54 -0700
changeset 10938 90e5cb81c483
permissions -rw-r--r--
Added an audio recording test program
     1 /*
     2   Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
     3 
     4   This software is provided 'as-is', without any express or implied
     5   warranty.  In no event will the authors be held liable for any damages
     6   arising from the use of this software.
     7 
     8   Permission is granted to anyone to use this software for any purpose,
     9   including commercial applications, and to alter it and redistribute it
    10   freely.
    11 */
    12 
    13 /* Program to record audio from the microphone and play it back immediately */
    14 
    15 #include "SDL_config.h"
    16 
    17 #include <stdio.h>
    18 #include <stdlib.h>
    19 
    20 #if HAVE_SIGNAL_H
    21 #include <signal.h>
    22 #endif
    23 
    24 #ifdef __EMSCRIPTEN__
    25 #include <emscripten/emscripten.h>
    26 #endif
    27 
    28 #include "SDL.h"
    29 
    30 static SDL_AudioDeviceID device;
    31 static SDL_AudioDeviceID capture;
    32 
    33 static void SDLCALL
    34 fillerup(void *unused, Uint8 * stream, int len)
    35 {
    36 	SDL_QueueAudio(device, stream, len);
    37 }
    38 
    39 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
    40 static void
    41 quit(int rc)
    42 {
    43     SDL_Quit();
    44     exit(rc);
    45 }
    46 
    47 static void
    48 close_audio()
    49 {
    50     if (capture != 0) {
    51         SDL_CloseAudioDevice(capture);
    52         capture = 0;
    53     }
    54     if (device != 0) {
    55         SDL_CloseAudioDevice(device);
    56         device = 0;
    57     }
    58 }
    59 
    60 static void
    61 open_audio()
    62 {
    63     SDL_AudioSpec spec;
    64 
    65     SDL_zero(spec);
    66     spec.freq = 44100;
    67     spec.format = AUDIO_S16;
    68     spec.channels = 1;
    69     spec.samples = 1024;
    70     spec.callback = fillerup;
    71 
    72 	capture = SDL_OpenAudioDevice(NULL, SDL_TRUE, &spec, &spec, SDL_AUDIO_ALLOW_ANY_CHANGE);
    73 	if (!capture) {
    74 		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open microphone: %s\n", SDL_GetError());
    75 		quit(2);
    76 	}
    77 
    78 	spec.callback = NULL;
    79 
    80 	device = SDL_OpenAudioDevice(NULL, SDL_FALSE, &spec, NULL, 0);
    81     if (!device) {
    82         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open audio: %s\n", SDL_GetError());
    83         quit(2);
    84     }
    85 
    86 	/* Let the audio run */
    87 	SDL_PauseAudioDevice(capture, SDL_FALSE);
    88     SDL_PauseAudioDevice(device, SDL_FALSE);
    89 }
    90 
    91 static void reopen_audio()
    92 {
    93     close_audio();
    94     open_audio();
    95 }
    96 
    97 
    98 static int done = 0;
    99 void
   100 poked(int sig)
   101 {
   102     done = 1;
   103 }
   104 
   105 #ifdef __EMSCRIPTEN__
   106 void
   107 loop()
   108 {
   109     if(done || (SDL_GetAudioDeviceStatus(capture) != SDL_AUDIO_PLAYING) || (SDL_GetAudioDeviceStatus(device) != SDL_AUDIO_PLAYING))
   110         emscripten_cancel_main_loop();
   111 }
   112 #endif
   113 
   114 int
   115 main(int argc, char *argv[])
   116 {
   117     int i;
   118 
   119     /* Enable standard application logging */
   120     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   121 
   122     /* Load the SDL library */
   123     if (SDL_Init(SDL_INIT_AUDIO|SDL_INIT_EVENTS) < 0) {
   124         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
   125         return (1);
   126     }
   127 
   128     /* Show the list of available drivers */
   129     SDL_Log("Available audio drivers:");
   130     for (i = 0; i < SDL_GetNumAudioDrivers(); ++i) {
   131         SDL_Log("%i: %s", i, SDL_GetAudioDriver(i));
   132     }
   133 
   134     SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
   135 
   136     open_audio();
   137 
   138     SDL_FlushEvents(SDL_AUDIODEVICEADDED, SDL_AUDIODEVICEREMOVED);
   139 
   140 #ifdef __EMSCRIPTEN__
   141     emscripten_set_main_loop(loop, 0, 1);
   142 #else
   143     while (!done) {
   144         SDL_Event event;
   145 
   146         while (SDL_PollEvent(&event) > 0) {
   147             if (event.type == SDL_QUIT) {
   148                 done = 1;
   149             }
   150             if (event.type == SDL_AUDIODEVICEADDED ||
   151                 (event.type == SDL_AUDIODEVICEREMOVED && event.adevice.iscapture && event.adevice.which == capture) ||
   152                 (event.type == SDL_AUDIODEVICEREMOVED && !event.adevice.iscapture && event.adevice.which == device)) {
   153                 reopen_audio();
   154             }
   155         }
   156         SDL_Delay(100);
   157     }
   158 #endif
   159 
   160     /* Clean up on signal */
   161     close_audio();
   162     SDL_Quit();
   163     return (0);
   164 }
   165 
   166 /* vi: set ts=4 sw=4 expandtab: */