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