00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_DIRECTCAM
00024
00025 #define WIN32_LEAN_AND_MEAN
00026
00027 #undef Configure
00028
00029 #include <windows.h>
00030 #include <mmsystem.h>
00031
00032
00033
00034
00035
00036
00037 class MicrophoneAudioDS : public MicrophoneAudio
00038 {
00039 public:
00040 static void find_all_microphones_ds();
00041 friend void find_all_microphones_ds();
00042
00043 private:
00044 virtual PT(MovieAudioCursor) open();
00045
00046 int _device_id;
00047 int _manufacturer_id;
00048 int _product_id;
00049
00050 struct AudioBuf {
00051 HGLOBAL _storage_gh;
00052 HGLOBAL _header_gh;
00053 LPSTR _storage;
00054 LPWAVEHDR _header;
00055 };
00056 typedef pvector <AudioBuf> AudioBuffers;
00057
00058 static void delete_buffers(AudioBuffers &buffers);
00059
00060 friend class MicrophoneAudioCursorDS;
00061
00062 public:
00063 static TypeHandle get_class_type() {
00064 return _type_handle;
00065 }
00066 static void init_type() {
00067 MicrophoneAudio::init_type();
00068 register_type(_type_handle, "MicrophoneAudioDS",
00069 MicrophoneAudio::get_class_type());
00070 }
00071 virtual TypeHandle get_type() const {
00072 return get_class_type();
00073 }
00074 virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00075
00076 private:
00077 static TypeHandle _type_handle;
00078 };
00079
00080 TypeHandle MicrophoneAudioDS::_type_handle;
00081
00082
00083
00084
00085
00086
00087 class MicrophoneAudioCursorDS : public MovieAudioCursor
00088 {
00089 public:
00090 typedef MicrophoneAudioDS::AudioBuffers AudioBuffers;
00091 MicrophoneAudioCursorDS(MicrophoneAudioDS *src, AudioBuffers &bufs, HWAVEIN hwav);
00092 virtual ~MicrophoneAudioCursorDS();
00093
00094 AudioBuffers _buffers;
00095 HWAVEIN _hwavein;
00096 int _samples_per_buffer;
00097
00098 public:
00099 virtual void read_samples(int n, PN_int16 *data);
00100 virtual int ready() const;
00101
00102 public:
00103 void cleanup();
00104
00105 HWAVEIN _handle;
00106 int _next;
00107 int _offset;
00108
00109 public:
00110 static TypeHandle get_class_type() {
00111 return _type_handle;
00112 }
00113 static void init_type() {
00114 MovieAudioCursor::init_type();
00115 register_type(_type_handle, "MicrophoneAudioCursorDS",
00116 MovieAudioCursor::get_class_type());
00117 }
00118 virtual TypeHandle get_type() const {
00119 return get_class_type();
00120 }
00121 virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00122
00123 private:
00124 static TypeHandle _type_handle;
00125 };
00126
00127 TypeHandle MicrophoneAudioCursorDS::_type_handle;
00128
00129
00130
00131
00132
00133
00134
00135 void MicrophoneAudioDS::
00136 find_all_microphones_ds() {
00137 MMRESULT stat;
00138 static int freqs[] = { 11025, 22050, 44100, 48000, 0 };
00139
00140 int ndevs = waveInGetNumDevs();
00141 for (int i=0; i<ndevs; i++) {
00142 WAVEINCAPS caps;
00143 stat = waveInGetDevCaps(i, &caps, sizeof(caps));
00144 if (stat != MMSYSERR_NOERROR) continue;
00145 for (int chan=1; chan<=2; chan++) {
00146 for (int fselect=0; freqs[fselect]; fselect++) {
00147 WAVEFORMATEX format;
00148 int freq = freqs[fselect];
00149 format.wFormatTag = WAVE_FORMAT_PCM;
00150 format.nChannels = chan;
00151 format.nSamplesPerSec = freq;
00152 format.nAvgBytesPerSec = freq * chan * 2;
00153 format.nBlockAlign = 2 * chan;
00154 format.wBitsPerSample = 16;
00155 format.cbSize = 0;
00156 stat = waveInOpen(NULL, i, &format, NULL, NULL, WAVE_FORMAT_QUERY);
00157 if (stat == MMSYSERR_NOERROR) {
00158 PT(MicrophoneAudioDS) p = new MicrophoneAudioDS();
00159 ostringstream name;
00160 name << "WaveIn: " << caps.szPname << " Chan:" << chan << " HZ:" << freq;
00161 p->set_name(name.str());
00162 p->_device_id = i;
00163 p->_manufacturer_id = caps.wMid;
00164 p->_product_id = caps.wPid;
00165 p->_rate = freq;
00166 p->_channels = chan;
00167 _all_microphones.push_back((MicrophoneAudioDS*)p);
00168 }
00169 }
00170 }
00171 }
00172 }
00173
00174 void find_all_microphones_ds() {
00175 MicrophoneAudioDS::init_type();
00176
00177 MicrophoneAudioDS::find_all_microphones_ds();
00178 }
00179
00180
00181
00182
00183
00184
00185 void MicrophoneAudioDS::
00186 delete_buffers(AudioBuffers &buffers) {
00187 for (int i=0; i<(int)buffers.size(); i++) {
00188 AudioBuf &buf = buffers[i];
00189 if (buf._header_gh) {
00190 GlobalUnlock(buf._header_gh);
00191 GlobalFree(buf._header_gh);
00192 }
00193 if (buf._storage_gh) {
00194 GlobalUnlock(buf._storage_gh);
00195 GlobalFree(buf._storage_gh);
00196 }
00197 }
00198 buffers.clear();
00199 }
00200
00201
00202
00203
00204
00205
00206 PT(MovieAudioCursor) MicrophoneAudioDS::
00207 open() {
00208
00209
00210 int samples;
00211 switch (_rate) {
00212 case 11025: samples=512; break;
00213 case 22050: samples=1024; break;
00214 case 44100: samples=2048; break;
00215 }
00216 int bytes = _channels * samples * 2;
00217
00218 bool failed = false;
00219 AudioBuffers buffers;
00220 for (int i=0; i<64; i++) {
00221 AudioBuf buf;
00222 buf._storage_gh = 0;
00223 buf._header_gh = 0;
00224 buf._storage = 0;
00225 buf._header = 0;
00226
00227 buf._storage_gh = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, bytes);
00228 buf._header_gh = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR));
00229 if (buf._storage_gh != 0) {
00230 buf._storage = (LPSTR)GlobalLock(buf._storage_gh);
00231 }
00232 if (buf._header_gh != 0) {
00233 buf._header = (LPWAVEHDR)GlobalLock(buf._header_gh);
00234 }
00235 if (buf._storage && buf._header) {
00236 ZeroMemory(buf._header, sizeof(WAVEHDR));
00237 buf._header->lpData = buf._storage;
00238 buf._header->dwBufferLength = bytes;
00239 } else {
00240 failed = true;
00241 }
00242 buffers.push_back(buf);
00243 if (failed) break;
00244 }
00245
00246 if (failed) {
00247 delete_buffers(buffers);
00248 nassert_raise("Could not allocate audio input buffers.");
00249 return NULL;
00250 }
00251
00252 WAVEFORMATEX format;
00253 format.wFormatTag = WAVE_FORMAT_PCM;
00254 format.nChannels = _channels;
00255 format.nSamplesPerSec = _rate;
00256 format.nAvgBytesPerSec = _rate * _channels * 2;
00257 format.nBlockAlign = 2 * _channels;
00258 format.wBitsPerSample = 16;
00259 format.cbSize = 0;
00260
00261 HWAVEIN hwav;
00262 MMRESULT stat = waveInOpen(&hwav, _device_id, &format, NULL, NULL, CALLBACK_NULL);
00263
00264 if (stat != MMSYSERR_NOERROR) {
00265 delete_buffers(buffers);
00266 nassert_raise("Could not open audio input device.");
00267 return NULL;
00268 }
00269
00270 for (int i=0; i<(int)buffers.size(); i++) {
00271 stat = waveInPrepareHeader(hwav, buffers[i]._header, sizeof(WAVEHDR));
00272 if (stat == MMSYSERR_NOERROR) {
00273 stat = waveInAddBuffer(hwav, buffers[i]._header, sizeof(WAVEHDR));
00274 }
00275 if (stat != MMSYSERR_NOERROR) {
00276 waveInClose(hwav);
00277 delete_buffers(buffers);
00278 nassert_raise("Could not queue buffers for audio input device.");
00279 return NULL;
00280 }
00281 }
00282 stat = waveInStart(hwav);
00283 if (stat != MMSYSERR_NOERROR) {
00284 waveInClose(hwav);
00285 delete_buffers(buffers);
00286 nassert_raise("Could not start recording on input device.");
00287 return NULL;
00288 }
00289 return new MicrophoneAudioCursorDS(this, buffers, hwav);
00290 }
00291
00292
00293
00294
00295
00296
00297 MicrophoneAudioCursorDS::
00298 MicrophoneAudioCursorDS(MicrophoneAudioDS *src, AudioBuffers &bufs, HWAVEIN hwav) :
00299 MovieAudioCursor(src),
00300 _buffers(bufs),
00301 _handle(hwav),
00302 _next(0),
00303 _offset(0)
00304 {
00305 _audio_rate = src->get_rate();
00306 _audio_channels = src->get_channels();
00307 _length = 1.0E10;
00308 _can_seek = false;
00309 _can_seek_fast = false;
00310 _aborted = false;
00311 _samples_per_buffer = bufs[0]._header->dwBufferLength / (2 * _audio_channels);
00312 }
00313
00314
00315
00316
00317
00318
00319 void MicrophoneAudioCursorDS::
00320 cleanup() {
00321 if (_handle) {
00322 waveInClose(_handle);
00323 _handle = 0;
00324 }
00325 MicrophoneAudioDS::delete_buffers(_buffers);
00326 _next = 0;
00327 _offset = 0;
00328 }
00329
00330
00331
00332
00333
00334
00335 MicrophoneAudioCursorDS::
00336 ~MicrophoneAudioCursorDS() {
00337 cleanup();
00338 }
00339
00340
00341
00342
00343
00344
00345 void MicrophoneAudioCursorDS::
00346 read_samples(int n, PN_int16 *data) {
00347 int orign = n;
00348 if (_handle) {
00349 while (1) {
00350 int index = _next % _buffers.size();
00351 if ((_buffers[index]._header->dwFlags & WHDR_DONE)==0) {
00352 break;
00353 }
00354
00355
00356 PN_int16 *src = (PN_int16*)(_buffers[index]._storage);
00357 src += (_offset * _audio_channels);
00358
00359
00360 int samples = _samples_per_buffer;
00361 samples -= _offset;
00362 if (samples > n) samples = n;
00363
00364
00365 memcpy(data, src, samples * 2 * _audio_channels);
00366
00367
00368 data += samples * _audio_channels;
00369 n -= samples;
00370 _offset += samples;
00371 _samples_read += samples;
00372 if (_offset != _samples_per_buffer) {
00373 break;
00374 }
00375 _buffers[index]._header->dwFlags &= ~(WHDR_DONE);
00376 MMRESULT stat = waveInUnprepareHeader(_handle, _buffers[index]._header, sizeof(WAVEHDR));
00377 if (stat == MMSYSERR_NOERROR) {
00378 stat = waveInPrepareHeader(_handle, _buffers[index]._header, sizeof(WAVEHDR));
00379 }
00380 if (stat == MMSYSERR_NOERROR) {
00381 stat = waveInAddBuffer(_handle, _buffers[index]._header, sizeof(WAVEHDR));
00382 }
00383 if (stat != MMSYSERR_NOERROR) {
00384 movies_cat.error() << "Could not requeue audio buffers, closing microphone.\n";
00385 cleanup();
00386 break;
00387 }
00388 _next += 1;
00389 _offset = 0;
00390 }
00391 }
00392 if (n > 0) {
00393 memcpy(data, 0, n*2*_audio_channels);
00394 }
00395 }
00396
00397
00398
00399
00400
00401
00402 int MicrophoneAudioCursorDS::
00403 ready() const {
00404 if (_handle == 0) return 0;
00405 int total = 0;
00406 for (int i=0; i<(int)_buffers.size(); i++) {
00407 int index = (_next + i) % (_buffers.size());
00408 if ((_buffers[index]._header->dwFlags & WHDR_DONE)==0) {
00409 break;
00410 }
00411 total += _samples_per_buffer;
00412 }
00413 total -= _offset;
00414 return total;
00415 }
00416
00417
00418 #endif // HAVE_DIRECTSHOW