2 * $Logfile: /Freespace2/code/Sound/dscap.cpp $
7 * C module for DirectSoundCapture code
10 * Revision 1.2 2002/05/07 03:16:52 theoddone33
11 * The Great Newline Fix
13 * Revision 1.1.1.1 2002/05/03 03:28:10 root
17 * 2 10/07/98 10:54a Dave
20 * 1 10/07/98 10:51a Dave
22 * 11 5/05/98 4:49p Lawrance
23 * Put in code to authenticate A3D, improve A3D support
25 * 10 4/24/98 2:17a Lawrance
26 * Clear out record buffer when recording begins
28 * 9 3/24/98 9:37a Lawrance
29 * Only read up to a safe offset in the capture buffer.
31 * 8 3/22/98 7:13p Lawrance
32 * Get streaming of recording voice working
34 * 7 2/26/98 2:54p Lawrance
35 * Don't recreate capture buffer each time recording starts... just use
38 * 6 2/15/98 11:10p Lawrance
39 * more work on real-time voice system
41 * 5 2/15/98 4:43p Lawrance
42 * work on real-time voice
44 * 4 2/09/98 8:07p Lawrance
45 * get buffer create working
47 * 3 2/04/98 6:08p Lawrance
48 * Read function pointers from dsound.dll, further work on
51 * 2 2/03/98 11:53p Lawrance
52 * Adding support for DirectSoundCapture
54 * 1 2/03/98 4:48p Lawrance
63 int dscap_inited=0; // flag to indicate that DirectSoundCapture inited ok
64 int dscap_recording; // flag to indicate that sound is being recorded
66 static LPDIRECTSOUNDCAPTURE pDSC; // global capture interface
67 static LPDIRECTSOUNDCAPTUREBUFFER pDSCB; // global capture buffer
69 static WAVEFORMATEX Dscap_wfx;
71 static unsigned long Dscap_last_capture_offset;
73 // init the DirectSoundCapture system
84 if ( !pfn_DirectSoundCaptureCreate ) {
85 nprintf(( "Sound", "SOUND ==> Could not get DirectSoundCaptureCreate function pointer\n" ));
89 dsrval = pfn_DirectSoundCaptureCreate(NULL, &pDSC, NULL);
91 if ( dsrval != DS_OK ) {
92 nprintf(( "Sound", "SOUND ==> Error '%s' initializing DirectSoundCapture.\n", get_DSERR_text(dsrval) ));
104 void dscap_release_buffer()
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)
123 if ( !dscap_inited ) {
127 if ( !dscap_inited ) {
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;
137 wfx.nBlockAlign = (unsigned short)(wfx.nChannels * (wfx.wBitsPerSample / 8));
138 wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
140 Dscap_wfx = wfx; // save the recording format
143 dscap_release_buffer();
146 memset(&dscbd, 0, sizeof(DSCBUFFERDESC));
147 dscbd.dwSize = sizeof(DSCBUFFERDESC);
148 dscbd.dwBufferBytes = wfx.nAvgBytesPerSec * nseconds;
149 dscbd.lpwfxFormat = &wfx;
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) ));
157 Dscap_last_capture_offset=0;
161 // check if DirectSoundCapture is supported
162 int dscap_supported()
164 if ( !dscap_inited ) {
170 // fill up the capture buffer with silence
171 int dscap_fill_buffer_with_silence()
174 unsigned long buffer_len, size1, size2;
175 void *data1=NULL, *data2=NULL;
177 buffer_len = dscap_max_buffersize();
181 dsrval = pDSCB->Lock(0, buffer_len, &data1, &size1, &data2, &size2, 0);
182 if ( dsrval != DS_OK ) {
186 unsigned char silence_byte;
188 switch(Dscap_wfx.wBitsPerSample) {
200 if ( (data1) && (size1 > 0) ) {
201 memset(data1, silence_byte, size1);
204 if ( (data2) && (size2 > 0) ) {
205 memset(data2, silence_byte, size2);
208 dsrval = pDSCB->Unlock(data1, size1, data2, size2);
209 if ( dsrval != DS_OK ) {
216 // start recording into the buffer
217 int dscap_start_record()
221 if ( !dscap_inited ) {
225 if ( !dscap_inited ) {
229 if ( dscap_recording ) {
235 dscap_fill_buffer_with_silence();
237 dsrval = pDSCB->Start(DSCBSTART_LOOPING);
238 if ( dsrval != DS_OK ) {
243 // nprintf(("Alan","RTVOICE => start record\n"));
247 // stop recording into the buffer
248 int dscap_stop_record()
252 if ( !dscap_inited ) {
256 if ( !dscap_recording ) {
261 dsrval = pDSCB->Stop();
262 if ( dsrval != DS_OK ) {
267 // nprintf(("Alan","RTVOICE => stop record\n"));
271 // close the DirectSoundCapture system
275 dscap_release_buffer();
283 // return the max buffer size
284 int dscap_max_buffersize()
288 if ( !dscap_inited ) {
292 if ( !dscap_inited ) {
300 caps.dwSize = sizeof(DSCBCAPS);
303 pDSCB->GetCaps(&caps);
305 return caps.dwBufferBytes;
308 // retreive the recorded voice data
309 int dscap_get_raw_data(unsigned char *outbuf, unsigned int max_size)
312 unsigned long capture_offset, read_offset, num_bytes_captured, size1, size2;
313 void *data1=NULL, *data2=NULL;
315 if ( !dscap_inited ) {
319 if ( !dscap_inited ) {
327 dsrval = pDSCB->GetCurrentPosition(&capture_offset, &read_offset);
328 if ( dsrval != DS_OK ) {
332 if ( read_offset >= Dscap_last_capture_offset ) {
333 num_bytes_captured = read_offset-Dscap_last_capture_offset;
335 unsigned long max_size = dscap_max_buffersize();
336 num_bytes_captured = max_size - Dscap_last_capture_offset + read_offset;
339 if ( num_bytes_captured <= 0 ) {
343 dsrval = pDSCB->Lock(Dscap_last_capture_offset, num_bytes_captured, &data1, &size1, &data2, &size2, 0);
344 if ( dsrval != DS_OK ) {
348 if ( max_size < (size1+size2) ) {
352 if ( (data1) && (size1 > 0) ) {
353 memcpy(outbuf, data1, size1);
356 if ( (data2) && (size2 > 0) ) {
357 memcpy(outbuf+size1, data2, size2);
360 dsrval = pDSCB->Unlock(data1, size1, data2, size2);
361 if ( dsrval != DS_OK ) {
365 Dscap_last_capture_offset = read_offset;
366 return (size1+size2);