]> icculus.org git repositories - taylor/freespace2.git/blob - src/sound/oal_capture.cpp
plug demo upsells into the game event/state system
[taylor/freespace2.git] / src / sound / oal_capture.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9
10 #include <string>
11
12 #include "pstypes.h"
13 #include "oal.h"
14 #include "osregistry.h"
15
16 #ifndef __EMSCRIPTEN__
17
18 static int OAL_capture_recording = 0;
19
20 struct capture_buffer {
21         uint samples_per_second;
22         uint bits_per_sample;
23         uint n_channels;
24         uint block_align;
25
26         ALenum format;
27         ALsizei buffer_size;
28 };
29
30 static capture_buffer Capture;
31
32 static ALCdevice *al_capture_device = NULL;
33 static std::string CaptureDevice;
34
35 #endif
36
37 void oal_capture_release_buffer()
38 {
39 #ifndef __EMSCRIPTEN__
40         if (al_capture_device != NULL) {
41                 alcCaptureCloseDevice(al_capture_device);
42                 al_capture_device = NULL;
43         }
44 #endif
45 }
46
47 // create a capture buffer with the specified format
48 // exit:        0       ->              buffer created successfully
49 //                      !0      ->              error creating the buffer
50 int oal_capture_create_buffer(int freq, int bits_per_sample, int nchannels, int nseconds)
51 {
52 #ifndef __EMSCRIPTEN__
53         ALenum al_format = AL_FORMAT_MONO8;
54         ALsizei buf_size = freq * nseconds;
55
56         SDL_assert( (nchannels == 1) || (nchannels == 2) );
57         SDL_assert( (bits_per_sample == 8) || (bits_per_sample == 16) );
58
59         if ( !oal_is_initted() ) {
60                 return -1;
61         }
62
63         if (nchannels == 1) {
64                 if (bits_per_sample == 8)  {
65                         al_format = AL_FORMAT_MONO8;
66                 } else if (bits_per_sample == 16) {
67                         al_format = AL_FORMAT_MONO16;
68                 }
69         } else if (nchannels == 2) {
70                 if (bits_per_sample == 8) {
71                         al_format = AL_FORMAT_STEREO8;
72                 } else if (bits_per_sample == 16) {
73                         al_format = AL_FORMAT_STEREO16;
74                 }
75         }
76
77         al_capture_device = alcCaptureOpenDevice(CaptureDevice.c_str(), freq, al_format, buf_size);
78
79         if (al_capture_device == NULL) {
80                 return -1;
81         }
82
83         // this gets around hang-on-close bug on Windows
84         alcCaptureStart(al_capture_device);
85         alcCaptureStop(al_capture_device);
86
87         if ( alcGetError(al_capture_device) != ALC_NO_ERROR ) {
88                 alcCaptureCloseDevice(al_capture_device);
89
90                 return -1;
91         }
92
93         Capture.format = al_format;
94         Capture.bits_per_sample = bits_per_sample;
95         Capture.n_channels = nchannels;
96         Capture.samples_per_second = freq;
97         Capture.block_align = (nchannels * bits_per_sample) / 8;
98
99         return 0;
100 #else
101         return -1;
102 #endif
103 }
104
105 void oal_capture_init()
106 {
107 #ifndef __EMSCRIPTEN__
108         const char *ptr = NULL;
109         ALCdevice *tdevice = NULL;
110
111         ptr = os_config_read_string("Audio", "CaptureDevice", "default");
112
113         if ( ptr && !SDL_strcasecmp(ptr, "default") ) {
114                 ptr = NULL;
115         }
116
117         tdevice = alcCaptureOpenDevice(ptr, 11025, AL_FORMAT_MONO8, 11025 * 2);
118
119         if (tdevice == NULL) {
120                 tdevice = alcCaptureOpenDevice(NULL, 11025, AL_FORMAT_MONO8, 11025 * 2);
121
122                 if (tdevice == NULL) {
123                         mprintf(("  Capture device  : * Unavailable *\n"));
124
125                         return;
126                 }
127         }
128
129         if ( alcGetError(tdevice) != ALC_NO_ERROR ) {
130                 mprintf(("  Capture device  : * Unavailable *\n"));
131                 alcCaptureCloseDevice(tdevice);
132
133                 return;
134         }
135
136         ptr = alcGetString(tdevice, ALC_CAPTURE_DEVICE_SPECIFIER);
137         SDL_assert( ptr );
138
139         mprintf(("  Capture device  : %s\n", ptr));
140
141         CaptureDevice = ptr;
142
143         // this gets around hang-on-close bug on Windows
144         alcCaptureStart(tdevice);
145         alcCaptureStop(tdevice);
146
147         alcCaptureCloseDevice(tdevice);
148 #endif
149 }
150
151 int oal_capture_supported()
152 {
153 #ifndef __EMSCRIPTEN__
154         return oal_is_initted();
155 #else
156         return 0;
157 #endif
158 }
159
160 // start recording into the buffer
161 int oal_capture_start_record()
162 {
163 #ifndef __EMSCRIPTEN__
164         if ( !oal_is_initted() ) {
165                 return -1;
166         }
167
168         if (OAL_capture_recording) {
169                 return -1;
170         }
171
172         alcCaptureStart(al_capture_device);
173
174         OAL_capture_recording = 1;
175
176 //      nprintf(("Alan","RTVOICE => start record\n"));
177
178         return 0;
179 #else
180         return -1;
181 #endif
182 }
183
184 // stop recording into the buffer
185 int oal_capture_stop_record()
186 {
187 #ifndef __EMSCRIPTEN__
188         if ( !oal_is_initted() ) {
189                 return -1;
190         }
191
192         if ( !OAL_capture_recording ) {
193                 return -1;
194         }
195
196         alcCaptureStop(al_capture_device);
197
198         OAL_capture_recording = 0;
199
200 //      nprintf(("Alan","RTVOICE => stop record\n"));
201
202         return 0;
203 #else
204         return -1;
205 #endif
206 }
207
208 void oal_capture_close()
209 {
210 #ifndef __EMSCRIPTEN__
211         oal_capture_stop_record();
212
213         if (al_capture_device != NULL) {
214                 alcCaptureCloseDevice(al_capture_device);
215                 al_capture_device = NULL;
216         }
217 #endif
218 }
219
220 // return the max buffer size
221 int oal_capture_max_buffersize()
222 {
223 #ifndef __EMSCRIPTEN__
224         if ( !oal_is_initted() ) {
225                 return 0;
226         }
227
228         ALCsizei num_samples = 0;
229
230         alcGetIntegerv(al_capture_device, ALC_CAPTURE_SAMPLES, sizeof(ALCsizei), &num_samples);
231
232         if (alcGetError(al_capture_device) != ALC_NO_ERROR) {
233                 return 0;
234         }
235
236         return (num_samples * Capture.block_align);
237 #else
238         return 0;
239 #endif
240 }
241
242 // retrieve the recorded voice data
243 int oal_capture_get_raw_data(ubyte *outbuf, uint max_size)
244 {
245 #ifndef __EMSCRIPTEN__
246         if ( !oal_is_initted() ) {
247                 return 0;
248         }
249
250         if (outbuf == NULL) {
251                 return 0;
252         }
253
254         ALCsizei num_samples = 0;
255
256         alcGetIntegerv(al_capture_device, ALC_CAPTURE_SAMPLES, sizeof(ALCsizei), &num_samples);
257
258         if (num_samples <= 0) {
259                 return 0;
260         }
261
262         ALCsizei max_buf_size = SDL_min(num_samples, ALsizei(max_size / Capture.block_align));
263
264         alcCaptureSamples(al_capture_device, outbuf, max_buf_size);
265
266         if (alcGetError(al_capture_device) != ALC_NO_ERROR) {
267                 return 0;
268         }
269
270         return (int)max_buf_size * Capture.block_align;
271 #else
272         return 0;
273 #endif
274 }