1 | /* |
2 | Copyright (C) 1997-2021 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 | #include "SDL.h" |
13 | |
14 | #include <stdlib.h> |
15 | |
16 | #ifdef __EMSCRIPTEN__ |
17 | #include <emscripten/emscripten.h> |
18 | #endif |
19 | |
20 | static SDL_Window *window = NULL; |
21 | static SDL_Renderer *renderer = NULL; |
22 | static SDL_AudioSpec spec; |
23 | static SDL_AudioDeviceID devid_in = 0; |
24 | static SDL_AudioDeviceID devid_out = 0; |
25 | |
26 | static void |
27 | loop() |
28 | { |
29 | SDL_bool please_quit = SDL_FALSE; |
30 | SDL_Event e; |
31 | |
32 | while (SDL_PollEvent(&e)) { |
33 | if (e.type == SDL_QUIT) { |
34 | please_quit = SDL_TRUE; |
35 | } else if (e.type == SDL_KEYDOWN) { |
36 | if (e.key.keysym.sym == SDLK_ESCAPE) { |
37 | please_quit = SDL_TRUE; |
38 | } |
39 | } else if (e.type == SDL_MOUSEBUTTONDOWN) { |
40 | if (e.button.button == 1) { |
41 | SDL_PauseAudioDevice(devid_out, SDL_TRUE); |
42 | SDL_PauseAudioDevice(devid_in, SDL_FALSE); |
43 | } |
44 | } else if (e.type == SDL_MOUSEBUTTONUP) { |
45 | if (e.button.button == 1) { |
46 | SDL_PauseAudioDevice(devid_in, SDL_TRUE); |
47 | SDL_PauseAudioDevice(devid_out, SDL_FALSE); |
48 | } |
49 | } |
50 | } |
51 | |
52 | if (SDL_GetAudioDeviceStatus(devid_in) == SDL_AUDIO_PLAYING) { |
53 | SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); |
54 | } else { |
55 | SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); |
56 | } |
57 | SDL_RenderClear(renderer); |
58 | SDL_RenderPresent(renderer); |
59 | |
60 | if (please_quit) { |
61 | /* stop playing back, quit. */ |
62 | SDL_Log("Shutting down.\n" ); |
63 | SDL_PauseAudioDevice(devid_in, 1); |
64 | SDL_CloseAudioDevice(devid_in); |
65 | SDL_PauseAudioDevice(devid_out, 1); |
66 | SDL_CloseAudioDevice(devid_out); |
67 | SDL_DestroyRenderer(renderer); |
68 | SDL_DestroyWindow(window); |
69 | SDL_Quit(); |
70 | #ifdef __EMSCRIPTEN__ |
71 | emscripten_cancel_main_loop(); |
72 | #endif |
73 | exit(0); |
74 | } |
75 | |
76 | /* Note that it would be easier to just have a one-line function that |
77 | calls SDL_QueueAudio() as a capture device callback, but we're |
78 | trying to test the API, so we use SDL_DequeueAudio() here. */ |
79 | while (SDL_TRUE) { |
80 | Uint8 buf[1024]; |
81 | const Uint32 br = SDL_DequeueAudio(devid_in, buf, sizeof (buf)); |
82 | SDL_QueueAudio(devid_out, buf, br); |
83 | if (br < sizeof (buf)) { |
84 | break; |
85 | } |
86 | } |
87 | } |
88 | |
89 | int |
90 | main(int argc, char **argv) |
91 | { |
92 | /* (argv[1] == NULL means "open default device.") */ |
93 | const char *devname = argv[1]; |
94 | SDL_AudioSpec wanted; |
95 | int devcount; |
96 | int i; |
97 | |
98 | /* Enable standard application logging */ |
99 | SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); |
100 | |
101 | /* Load the SDL library */ |
102 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { |
103 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n" , SDL_GetError()); |
104 | return (1); |
105 | } |
106 | |
107 | window = SDL_CreateWindow("testaudiocapture" , SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 240, 0); |
108 | renderer = SDL_CreateRenderer(window, -1, 0); |
109 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); |
110 | SDL_RenderClear(renderer); |
111 | SDL_RenderPresent(renderer); |
112 | |
113 | SDL_Log("Using audio driver: %s\n" , SDL_GetCurrentAudioDriver()); |
114 | |
115 | devcount = SDL_GetNumAudioDevices(SDL_TRUE); |
116 | for (i = 0; i < devcount; i++) { |
117 | SDL_Log(" Capture device #%d: '%s'\n" , i, SDL_GetAudioDeviceName(i, SDL_TRUE)); |
118 | } |
119 | |
120 | SDL_zero(wanted); |
121 | wanted.freq = 44100; |
122 | wanted.format = AUDIO_F32SYS; |
123 | wanted.channels = 1; |
124 | wanted.samples = 4096; |
125 | wanted.callback = NULL; |
126 | |
127 | SDL_zero(spec); |
128 | |
129 | /* DirectSound can fail in some instances if you open the same hardware |
130 | for both capture and output and didn't open the output end first, |
131 | according to the docs, so if you're doing something like this, always |
132 | open your capture devices second in case you land in those bizarre |
133 | circumstances. */ |
134 | |
135 | SDL_Log("Opening default playback device...\n" ); |
136 | devid_out = SDL_OpenAudioDevice(NULL, SDL_FALSE, &wanted, &spec, SDL_AUDIO_ALLOW_ANY_CHANGE); |
137 | if (!devid_out) { |
138 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for playback: %s!\n" , SDL_GetError()); |
139 | SDL_Quit(); |
140 | exit(1); |
141 | } |
142 | |
143 | SDL_Log("Opening capture device %s%s%s...\n" , |
144 | devname ? "'" : "" , |
145 | devname ? devname : "[[default]]" , |
146 | devname ? "'" : "" ); |
147 | |
148 | devid_in = SDL_OpenAudioDevice(argv[1], SDL_TRUE, &spec, &spec, 0); |
149 | if (!devid_in) { |
150 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for capture: %s!\n" , SDL_GetError()); |
151 | SDL_Quit(); |
152 | exit(1); |
153 | } |
154 | |
155 | SDL_Log("Ready! Hold down mouse or finger to record!\n" ); |
156 | |
157 | #ifdef __EMSCRIPTEN__ |
158 | emscripten_set_main_loop(loop, 0, 1); |
159 | #else |
160 | while (1) { loop(); SDL_Delay(16); } |
161 | #endif |
162 | |
163 | return 0; |
164 | } |
165 | |
166 | |