2 * $Logfile: /Freespace2/code/Sound/dscap.cpp $
7 * C module for DirectSoundCapture code
10 * Revision 1.1 2002/05/03 03:28:10 root
14 * 2 10/07/98 10:54a Dave
17 * 1 10/07/98 10:51a Dave
19 * 11 5/05/98 4:49p Lawrance
20 * Put in code to authenticate A3D, improve A3D support
22 * 10 4/24/98 2:17a Lawrance
23 * Clear out record buffer when recording begins
25 * 9 3/24/98 9:37a Lawrance
26 * Only read up to a safe offset in the capture buffer.
28 * 8 3/22/98 7:13p Lawrance
29 * Get streaming of recording voice working
31 * 7 2/26/98 2:54p Lawrance
32 * Don't recreate capture buffer each time recording starts... just use
35 * 6 2/15/98 11:10p Lawrance
36 * more work on real-time voice system
38 * 5 2/15/98 4:43p Lawrance
39 * work on real-time voice
41 * 4 2/09/98 8:07p Lawrance
42 * get buffer create working
44 * 3 2/04/98 6:08p Lawrance
45 * Read function pointers from dsound.dll, further work on
48 * 2 2/03/98 11:53p Lawrance
49 * Adding support for DirectSoundCapture
51 * 1 2/03/98 4:48p Lawrance
60 int dscap_inited=0; // flag to indicate that DirectSoundCapture inited ok
61 int dscap_recording; // flag to indicate that sound is being recorded
63 static LPDIRECTSOUNDCAPTURE pDSC; // global capture interface
64 static LPDIRECTSOUNDCAPTUREBUFFER pDSCB; // global capture buffer
66 static WAVEFORMATEX Dscap_wfx;
68 static unsigned long Dscap_last_capture_offset;
70 // init the DirectSoundCapture system
81 if ( !pfn_DirectSoundCaptureCreate ) {
82 nprintf(( "Sound", "SOUND ==> Could not get DirectSoundCaptureCreate function pointer\n" ));
86 dsrval = pfn_DirectSoundCaptureCreate(NULL, &pDSC, NULL);
88 if ( dsrval != DS_OK ) {
89 nprintf(( "Sound", "SOUND ==> Error '%s' initializing DirectSoundCapture.\n", get_DSERR_text(dsrval) ));
101 void dscap_release_buffer()
111 // create a capture buffer with the specified format
112 // exit: 0 -> buffer created successfully
113 // !0 -> error creating the buffer
114 int dscap_create_buffer(int freq, int bits_per_sample, int nchannels, int nseconds)
120 if ( !dscap_inited ) {
124 if ( !dscap_inited ) {
128 // Set up recording format
129 wfx.wFormatTag = WAVE_FORMAT_PCM;
130 wfx.nChannels = (unsigned short)nchannels;
131 wfx.nSamplesPerSec = freq;
132 wfx.wBitsPerSample = (unsigned short)bits_per_sample;
134 wfx.nBlockAlign = (unsigned short)(wfx.nChannels * (wfx.wBitsPerSample / 8));
135 wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
137 Dscap_wfx = wfx; // save the recording format
140 dscap_release_buffer();
143 memset(&dscbd, 0, sizeof(DSCBUFFERDESC));
144 dscbd.dwSize = sizeof(DSCBUFFERDESC);
145 dscbd.dwBufferBytes = wfx.nAvgBytesPerSec * nseconds;
146 dscbd.lpwfxFormat = &wfx;
148 dsrval = pDSC->CreateCaptureBuffer(&dscbd, &pDSCB, NULL);
149 if ( dsrval != DS_OK ) {
150 nprintf(( "Sound", "SOUND ==> Error '%s' creating a DirectSoundCapture buffer.\n", get_DSERR_text(dsrval) ));
154 Dscap_last_capture_offset=0;
158 // check if DirectSoundCapture is supported
159 int dscap_supported()
161 if ( !dscap_inited ) {
167 // fill up the capture buffer with silence
168 int dscap_fill_buffer_with_silence()
171 unsigned long buffer_len, size1, size2;
172 void *data1=NULL, *data2=NULL;
174 buffer_len = dscap_max_buffersize();
178 dsrval = pDSCB->Lock(0, buffer_len, &data1, &size1, &data2, &size2, 0);
179 if ( dsrval != DS_OK ) {
183 unsigned char silence_byte;
185 switch(Dscap_wfx.wBitsPerSample) {
197 if ( (data1) && (size1 > 0) ) {
198 memset(data1, silence_byte, size1);
201 if ( (data2) && (size2 > 0) ) {
202 memset(data2, silence_byte, size2);
205 dsrval = pDSCB->Unlock(data1, size1, data2, size2);
206 if ( dsrval != DS_OK ) {
213 // start recording into the buffer
214 int dscap_start_record()
218 if ( !dscap_inited ) {
222 if ( !dscap_inited ) {
226 if ( dscap_recording ) {
232 dscap_fill_buffer_with_silence();
234 dsrval = pDSCB->Start(DSCBSTART_LOOPING);
235 if ( dsrval != DS_OK ) {
240 // nprintf(("Alan","RTVOICE => start record\n"));
244 // stop recording into the buffer
245 int dscap_stop_record()
249 if ( !dscap_inited ) {
253 if ( !dscap_recording ) {
258 dsrval = pDSCB->Stop();
259 if ( dsrval != DS_OK ) {
264 // nprintf(("Alan","RTVOICE => stop record\n"));
268 // close the DirectSoundCapture system
272 dscap_release_buffer();
280 // return the max buffer size
281 int dscap_max_buffersize()
285 if ( !dscap_inited ) {
289 if ( !dscap_inited ) {
297 caps.dwSize = sizeof(DSCBCAPS);
300 pDSCB->GetCaps(&caps);
302 return caps.dwBufferBytes;
305 // retreive the recorded voice data
306 int dscap_get_raw_data(unsigned char *outbuf, unsigned int max_size)
309 unsigned long capture_offset, read_offset, num_bytes_captured, size1, size2;
310 void *data1=NULL, *data2=NULL;
312 if ( !dscap_inited ) {
316 if ( !dscap_inited ) {
324 dsrval = pDSCB->GetCurrentPosition(&capture_offset, &read_offset);
325 if ( dsrval != DS_OK ) {
329 if ( read_offset >= Dscap_last_capture_offset ) {
330 num_bytes_captured = read_offset-Dscap_last_capture_offset;
332 unsigned long max_size = dscap_max_buffersize();
333 num_bytes_captured = max_size - Dscap_last_capture_offset + read_offset;
336 if ( num_bytes_captured <= 0 ) {
340 dsrval = pDSCB->Lock(Dscap_last_capture_offset, num_bytes_captured, &data1, &size1, &data2, &size2, 0);
341 if ( dsrval != DS_OK ) {
345 if ( max_size < (size1+size2) ) {
349 if ( (data1) && (size1 > 0) ) {
350 memcpy(outbuf, data1, size1);
353 if ( (data2) && (size2 > 0) ) {
354 memcpy(outbuf+size1, data2, size2);
357 dsrval = pDSCB->Unlock(data1, size1, data2, size2);
358 if ( dsrval != DS_OK ) {
362 Dscap_last_capture_offset = read_offset;
363 return (size1+size2);