2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/Sound/dscap.cpp $
15 * C module for DirectSoundCapture code
18 * Revision 1.3 2002/06/09 04:41:27 relnev
19 * added copyright header
21 * Revision 1.2 2002/05/07 03:16:52 theoddone33
22 * The Great Newline Fix
24 * Revision 1.1.1.1 2002/05/03 03:28:10 root
28 * 2 10/07/98 10:54a Dave
31 * 1 10/07/98 10:51a Dave
33 * 11 5/05/98 4:49p Lawrance
34 * Put in code to authenticate A3D, improve A3D support
36 * 10 4/24/98 2:17a Lawrance
37 * Clear out record buffer when recording begins
39 * 9 3/24/98 9:37a Lawrance
40 * Only read up to a safe offset in the capture buffer.
42 * 8 3/22/98 7:13p Lawrance
43 * Get streaming of recording voice working
45 * 7 2/26/98 2:54p Lawrance
46 * Don't recreate capture buffer each time recording starts... just use
49 * 6 2/15/98 11:10p Lawrance
50 * more work on real-time voice system
52 * 5 2/15/98 4:43p Lawrance
53 * work on real-time voice
55 * 4 2/09/98 8:07p Lawrance
56 * get buffer create working
58 * 3 2/04/98 6:08p Lawrance
59 * Read function pointers from dsound.dll, further work on
62 * 2 2/03/98 11:53p Lawrance
63 * Adding support for DirectSoundCapture
65 * 1 2/03/98 4:48p Lawrance
74 int dscap_inited=0; // flag to indicate that DirectSoundCapture inited ok
75 int dscap_recording; // flag to indicate that sound is being recorded
77 static LPDIRECTSOUNDCAPTURE pDSC; // global capture interface
78 static LPDIRECTSOUNDCAPTUREBUFFER pDSCB; // global capture buffer
80 static WAVEFORMATEX Dscap_wfx;
82 static unsigned long Dscap_last_capture_offset;
84 // init the DirectSoundCapture system
95 if ( !pfn_DirectSoundCaptureCreate ) {
96 nprintf(( "Sound", "SOUND ==> Could not get DirectSoundCaptureCreate function pointer\n" ));
100 dsrval = pfn_DirectSoundCaptureCreate(NULL, &pDSC, NULL);
102 if ( dsrval != DS_OK ) {
103 nprintf(( "Sound", "SOUND ==> Error '%s' initializing DirectSoundCapture.\n", get_DSERR_text(dsrval) ));
115 void dscap_release_buffer()
125 // create a capture buffer with the specified format
126 // exit: 0 -> buffer created successfully
127 // !0 -> error creating the buffer
128 int dscap_create_buffer(int freq, int bits_per_sample, int nchannels, int nseconds)
134 if ( !dscap_inited ) {
138 if ( !dscap_inited ) {
142 // Set up recording format
143 wfx.wFormatTag = WAVE_FORMAT_PCM;
144 wfx.nChannels = (unsigned short)nchannels;
145 wfx.nSamplesPerSec = freq;
146 wfx.wBitsPerSample = (unsigned short)bits_per_sample;
148 wfx.nBlockAlign = (unsigned short)(wfx.nChannels * (wfx.wBitsPerSample / 8));
149 wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
151 Dscap_wfx = wfx; // save the recording format
154 dscap_release_buffer();
157 memset(&dscbd, 0, sizeof(DSCBUFFERDESC));
158 dscbd.dwSize = sizeof(DSCBUFFERDESC);
159 dscbd.dwBufferBytes = wfx.nAvgBytesPerSec * nseconds;
160 dscbd.lpwfxFormat = &wfx;
162 dsrval = pDSC->CreateCaptureBuffer(&dscbd, &pDSCB, NULL);
163 if ( dsrval != DS_OK ) {
164 nprintf(( "Sound", "SOUND ==> Error '%s' creating a DirectSoundCapture buffer.\n", get_DSERR_text(dsrval) ));
168 Dscap_last_capture_offset=0;
172 // check if DirectSoundCapture is supported
173 int dscap_supported()
175 if ( !dscap_inited ) {
181 // fill up the capture buffer with silence
182 int dscap_fill_buffer_with_silence()
185 unsigned long buffer_len, size1, size2;
186 void *data1=NULL, *data2=NULL;
188 buffer_len = dscap_max_buffersize();
192 dsrval = pDSCB->Lock(0, buffer_len, &data1, &size1, &data2, &size2, 0);
193 if ( dsrval != DS_OK ) {
197 unsigned char silence_byte;
199 switch(Dscap_wfx.wBitsPerSample) {
211 if ( (data1) && (size1 > 0) ) {
212 memset(data1, silence_byte, size1);
215 if ( (data2) && (size2 > 0) ) {
216 memset(data2, silence_byte, size2);
219 dsrval = pDSCB->Unlock(data1, size1, data2, size2);
220 if ( dsrval != DS_OK ) {
227 // start recording into the buffer
228 int dscap_start_record()
232 if ( !dscap_inited ) {
236 if ( !dscap_inited ) {
240 if ( dscap_recording ) {
246 dscap_fill_buffer_with_silence();
248 dsrval = pDSCB->Start(DSCBSTART_LOOPING);
249 if ( dsrval != DS_OK ) {
254 // nprintf(("Alan","RTVOICE => start record\n"));
258 // stop recording into the buffer
259 int dscap_stop_record()
263 if ( !dscap_inited ) {
267 if ( !dscap_recording ) {
272 dsrval = pDSCB->Stop();
273 if ( dsrval != DS_OK ) {
278 // nprintf(("Alan","RTVOICE => stop record\n"));
282 // close the DirectSoundCapture system
286 dscap_release_buffer();
294 // return the max buffer size
295 int dscap_max_buffersize()
299 if ( !dscap_inited ) {
303 if ( !dscap_inited ) {
311 caps.dwSize = sizeof(DSCBCAPS);
314 pDSCB->GetCaps(&caps);
316 return caps.dwBufferBytes;
319 // retreive the recorded voice data
320 int dscap_get_raw_data(unsigned char *outbuf, unsigned int max_size)
323 unsigned long capture_offset, read_offset, num_bytes_captured, size1, size2;
324 void *data1=NULL, *data2=NULL;
326 if ( !dscap_inited ) {
330 if ( !dscap_inited ) {
338 dsrval = pDSCB->GetCurrentPosition(&capture_offset, &read_offset);
339 if ( dsrval != DS_OK ) {
343 if ( read_offset >= Dscap_last_capture_offset ) {
344 num_bytes_captured = read_offset-Dscap_last_capture_offset;
346 unsigned long max_size = dscap_max_buffersize();
347 num_bytes_captured = max_size - Dscap_last_capture_offset + read_offset;
350 if ( num_bytes_captured <= 0 ) {
354 dsrval = pDSCB->Lock(Dscap_last_capture_offset, num_bytes_captured, &data1, &size1, &data2, &size2, 0);
355 if ( dsrval != DS_OK ) {
359 if ( max_size < (size1+size2) ) {
363 if ( (data1) && (size1 > 0) ) {
364 memcpy(outbuf, data1, size1);
367 if ( (data2) && (size2 > 0) ) {
368 memcpy(outbuf+size1, data2, size2);
371 dsrval = pDSCB->Unlock(data1, size1, data2, size2);
372 if ( dsrval != DS_OK ) {
376 Dscap_last_capture_offset = read_offset;
377 return (size1+size2);