]> icculus.org git repositories - taylor/freespace2.git/blob - src/sound/dscap.cpp
Fix net_addr vs net_addr_t
[taylor/freespace2.git] / src / sound / dscap.cpp
1 /*
2  * $Logfile: /Freespace2/code/Sound/dscap.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * C module for DirectSoundCapture code
8  *
9  * $Log$
10  * Revision 1.2  2002/05/07 03:16:52  theoddone33
11  * The Great Newline Fix
12  *
13  * Revision 1.1.1.1  2002/05/03 03:28:10  root
14  * Initial import.
15  *
16  * 
17  * 2     10/07/98 10:54a Dave
18  * Initial checkin.
19  * 
20  * 1     10/07/98 10:51a Dave
21  * 
22  * 11    5/05/98 4:49p Lawrance
23  * Put in code to authenticate A3D, improve A3D support
24  * 
25  * 10    4/24/98 2:17a Lawrance
26  * Clear out record buffer when recording begins
27  * 
28  * 9     3/24/98 9:37a Lawrance
29  * Only read up to a safe offset in the capture buffer.
30  * 
31  * 8     3/22/98 7:13p Lawrance
32  * Get streaming of recording voice working
33  * 
34  * 7     2/26/98 2:54p Lawrance
35  * Don't recreate capture buffer each time recording starts... just use
36  * one.
37  * 
38  * 6     2/15/98 11:10p Lawrance
39  * more work on real-time voice system
40  * 
41  * 5     2/15/98 4:43p Lawrance
42  * work on real-time voice
43  * 
44  * 4     2/09/98 8:07p Lawrance
45  * get buffer create working
46  * 
47  * 3     2/04/98 6:08p Lawrance
48  * Read function pointers from dsound.dll, further work on
49  * DirectSoundCapture.
50  * 
51  * 2     2/03/98 11:53p Lawrance
52  * Adding support for DirectSoundCapture
53  * 
54  * 1     2/03/98 4:48p Lawrance
55  *
56  * $NoKeywords: $
57  */
58
59 #include "pstypes.h"
60 #include "ds.h"
61 #include "dscap.h"
62
63 int dscap_inited=0;                                             // flag to indicate that DirectSoundCapture inited ok
64 int dscap_recording;                                            // flag to indicate that sound is being recorded
65
66 static LPDIRECTSOUNDCAPTURE                     pDSC;           // global capture interface
67 static LPDIRECTSOUNDCAPTUREBUFFER       pDSCB;  // global capture buffer
68
69 static WAVEFORMATEX     Dscap_wfx;
70
71 static unsigned long Dscap_last_capture_offset; 
72
73 // init the DirectSoundCapture system
74 // exit:        0       ->              success
75 //                      !0      ->              failure
76 int dscap_init()
77 {
78         HRESULT dsrval;
79
80         if ( dscap_inited ) {
81                 return 0;
82         }
83
84         if ( !pfn_DirectSoundCaptureCreate ) {
85                 nprintf(( "Sound", "SOUND ==> Could not get DirectSoundCaptureCreate function pointer\n" ));
86                 return -1;
87         }
88
89         dsrval = pfn_DirectSoundCaptureCreate(NULL, &pDSC, NULL);
90
91         if ( dsrval != DS_OK ) {
92                 nprintf(( "Sound", "SOUND ==> Error '%s' initializing DirectSoundCapture.\n", get_DSERR_text(dsrval)  ));
93                 return -1;
94         }               
95
96         pDSCB=NULL;
97
98         dscap_recording=0;
99         dscap_inited=1;
100
101         return 0;
102 }
103
104 void dscap_release_buffer()
105 {
106         if ( !pDSCB ) {
107                 return;
108         }
109
110         pDSCB->Release();
111         pDSCB = NULL;
112 }
113
114 // create a capture buffer with the specified format
115 // exit:        0       ->              buffer created successfully
116 //                      !0      ->              error creating the buffer
117 int dscap_create_buffer(int freq, int bits_per_sample, int nchannels, int nseconds)
118 {
119         HRESULT                 dsrval;
120         DSCBUFFERDESC   dscbd;
121         WAVEFORMATEX    wfx;
122
123         if ( !dscap_inited ) {
124                 dscap_init();
125         }
126
127         if ( !dscap_inited ) {
128                 return -1;
129         }
130
131         // Set up recording format
132         wfx.wFormatTag = WAVE_FORMAT_PCM;
133         wfx.nChannels = (unsigned short)nchannels;
134         wfx.nSamplesPerSec = freq;
135         wfx.wBitsPerSample = (unsigned short)bits_per_sample;
136         wfx.cbSize = 0;
137         wfx.nBlockAlign = (unsigned short)(wfx.nChannels * (wfx.wBitsPerSample / 8));
138         wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
139
140         Dscap_wfx = wfx;        // save the recording format
141
142         if ( pDSCB ) {
143                 dscap_release_buffer();
144         }
145
146         memset(&dscbd, 0, sizeof(DSCBUFFERDESC));
147         dscbd.dwSize = sizeof(DSCBUFFERDESC);
148         dscbd.dwBufferBytes = wfx.nAvgBytesPerSec * nseconds;
149         dscbd.lpwfxFormat = &wfx;
150
151         dsrval = pDSC->CreateCaptureBuffer(&dscbd, &pDSCB, NULL);
152         if ( dsrval != DS_OK ) {
153                 nprintf(( "Sound", "SOUND ==> Error '%s' creating a DirectSoundCapture buffer.\n", get_DSERR_text(dsrval)  ));
154                 return -1;
155         }
156
157         Dscap_last_capture_offset=0;
158         return 0;
159 }
160
161 // check if DirectSoundCapture is supported
162 int dscap_supported()
163 {
164         if ( !dscap_inited ) {
165                 dscap_init();
166         }
167         return dscap_inited;
168 }
169
170 // fill up the capture buffer with silence
171 int dscap_fill_buffer_with_silence()
172 {
173         HRESULT                 dsrval;
174         unsigned long   buffer_len, size1, size2;
175         void                            *data1=NULL, *data2=NULL;
176
177         buffer_len = dscap_max_buffersize();
178
179         Assert(pDSCB);
180
181         dsrval = pDSCB->Lock(0, buffer_len, &data1, &size1, &data2, &size2, 0);
182         if ( dsrval != DS_OK ) {
183                 return -1;
184         }
185
186         unsigned char silence_byte;
187
188         switch(Dscap_wfx.wBitsPerSample) {
189         case 8:
190                 silence_byte = 0x80;
191                 break;
192         case 16:
193                 silence_byte = 0x00;
194                 break;
195         default:
196                 Int3();
197                 return -1;
198         }
199
200         if ( (data1) && (size1 > 0) ) {
201                 memset(data1, silence_byte, size1);
202         }
203
204         if ( (data2) && (size2 > 0) ) {
205                 memset(data2, silence_byte, size2);
206         }
207
208         dsrval = pDSCB->Unlock(data1, size1, data2, size2);
209         if ( dsrval != DS_OK ) {
210                 return -1;
211         }
212
213         return 0;
214 }
215
216 // start recording into the buffer
217 int dscap_start_record()
218 {
219         HRESULT dsrval;
220
221         if ( !dscap_inited ) {
222                 dscap_init();
223         }
224
225         if ( !dscap_inited ) {
226                 return -1;
227         }
228
229         if ( dscap_recording ) {
230                 return -1;
231         }
232
233         Assert(pDSCB);
234
235         dscap_fill_buffer_with_silence();
236
237         dsrval = pDSCB->Start(DSCBSTART_LOOPING);
238         if ( dsrval != DS_OK ) {
239                 return -1;
240         }
241
242         dscap_recording=1;
243 //      nprintf(("Alan","RTVOICE => start record\n"));
244         return 0;
245 }
246
247 // stop recording into the buffer
248 int dscap_stop_record()
249 {
250         HRESULT dsrval;
251
252         if ( !dscap_inited ) {
253                 return -1;
254         }
255
256         if ( !dscap_recording ) {
257                 return -1;
258         }
259
260         Assert(pDSCB);
261         dsrval = pDSCB->Stop();
262         if ( dsrval != DS_OK ) {
263                 return -1;
264         }
265
266         dscap_recording=0;
267 //      nprintf(("Alan","RTVOICE => stop record\n"));
268         return 0;
269 }
270
271 // close the DirectSoundCapture system
272 void dscap_close()
273 {
274         dscap_stop_record();
275         dscap_release_buffer();
276
277         if ( pDSC ) {
278                 pDSC->Release();
279                 pDSC=NULL;
280         }
281 }
282
283 // return the max buffer size
284 int dscap_max_buffersize()
285 {
286         DSCBCAPS        caps;
287
288         if ( !dscap_inited ) {
289                 dscap_init();
290         }
291
292         if ( !dscap_inited ) {
293                 return -1;
294         }
295
296         if (!pDSCB) {
297                 return 0;
298         }
299
300         caps.dwSize = sizeof(DSCBCAPS);
301         caps.dwFlags = 0;
302
303         pDSCB->GetCaps(&caps);
304
305         return caps.dwBufferBytes;
306 }
307
308 // retreive the recorded voice data
309 int dscap_get_raw_data(unsigned char *outbuf, unsigned int max_size)
310 {
311         HRESULT                 dsrval;
312         unsigned long   capture_offset, read_offset, num_bytes_captured, size1, size2;
313         void                            *data1=NULL, *data2=NULL;
314
315         if ( !dscap_inited ) {
316                 dscap_init();
317         }
318
319         if ( !dscap_inited ) {
320                 return -1;
321         }
322
323         if ( !pDSCB ) {
324                 return -1;
325         }
326
327         dsrval = pDSCB->GetCurrentPosition(&capture_offset, &read_offset);
328         if ( dsrval != DS_OK ) {
329                 return -1;
330         }
331
332         if ( read_offset >= Dscap_last_capture_offset ) {
333                 num_bytes_captured = read_offset-Dscap_last_capture_offset;
334         } else {
335                 unsigned long max_size = dscap_max_buffersize();
336                 num_bytes_captured = max_size - Dscap_last_capture_offset + read_offset;
337         }
338
339         if ( num_bytes_captured <= 0 ) {
340                 return -1;
341         }       
342
343         dsrval = pDSCB->Lock(Dscap_last_capture_offset, num_bytes_captured, &data1, &size1, &data2, &size2, 0);
344         if ( dsrval != DS_OK ) {
345                 return -1;
346         }
347
348         if ( max_size < (size1+size2) ) {
349                 return -1;
350         }
351
352         if ( (data1) && (size1 > 0) ) {
353                 memcpy(outbuf, data1, size1);
354         }
355
356         if ( (data2) && (size2 > 0) ) {
357                 memcpy(outbuf+size1, data2, size2);
358         }
359
360         dsrval = pDSCB->Unlock(data1, size1, data2, size2);
361         if ( dsrval != DS_OK ) {
362                 return -1;
363         }
364
365         Dscap_last_capture_offset = read_offset;
366         return (size1+size2);
367 }
368