00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #include <windows.h>
00059 #include <mmsystem.h>
00060 #include <stdio.h>
00061 #include <stdlib.h>
00062 #include <string.h>
00063
00064 #include "prim_type.h"
00065 #include "ad.h"
00066
00067
00068 #define DEFAULT_N_WI_BUF 32
00069 #define WI_BUFSIZE 2500
00070
00071
00072
00073
00074 #ifdef _WIN32_WCE
00075 #include "ckd_alloc.h"
00076 static void
00077 wavein_error(char *src, int32 ret)
00078 {
00079 TCHAR errbuf[512];
00080 wchar_t* werrbuf;
00081 size_t len;
00082
00083 waveOutGetErrorText(ret, errbuf, sizeof(errbuf));
00084 len = mbstowcs(NULL, errbuf, 0) + 1;
00085 werrbuf = ckd_calloc(len, sizeof(*werrbuf));
00086 mbstowcs(werrbuf, errbuf, len);
00087
00088 OutputDebugStringW(werrbuf);
00089 }
00090
00091 #else
00092 static void
00093 wavein_error(char *src, int32 ret)
00094 {
00095 char errbuf[1024];
00096
00097 waveInGetErrorText(ret, errbuf, sizeof(errbuf));
00098 fprintf(stderr, "%s error %d: %s\n", src, ret, errbuf);
00099 }
00100 #endif
00101
00102
00103 static void
00104 wavein_free_buf(ad_wbuf_t * b)
00105 {
00106 GlobalUnlock(b->h_whdr);
00107 GlobalFree(b->h_whdr);
00108 GlobalUnlock(b->h_buf);
00109 GlobalFree(b->h_buf);
00110 }
00111
00112
00113 static int32
00114 wavein_alloc_buf(ad_wbuf_t * b, int32 samples_per_buf)
00115 {
00116 HGLOBAL h_buf;
00117 LPSTR p_buf;
00118 HGLOBAL h_whdr;
00119 LPWAVEHDR p_whdr;
00120
00121
00122 h_buf =
00123 GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
00124 samples_per_buf * sizeof(int16));
00125 if (!h_buf) {
00126 fprintf(stderr, "GlobalAlloc failed\n");
00127 return -1;
00128 }
00129 if ((p_buf = GlobalLock(h_buf)) == NULL) {
00130 GlobalFree(h_buf);
00131 fprintf(stderr, "GlobalLock failed\n");
00132 return -1;
00133 }
00134
00135
00136 h_whdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR));
00137 if (h_whdr == NULL) {
00138 GlobalUnlock(h_buf);
00139 GlobalFree(h_buf);
00140
00141 fprintf(stderr, "GlobalAlloc failed\n");
00142 return -1;
00143 }
00144 if ((p_whdr = GlobalLock(h_whdr)) == NULL) {
00145 GlobalUnlock(h_buf);
00146 GlobalFree(h_buf);
00147 GlobalFree(h_whdr);
00148
00149 fprintf(stderr, "GlobalLock failed\n");
00150 return -1;
00151 }
00152
00153 b->h_buf = h_buf;
00154 b->p_buf = p_buf;
00155 b->h_whdr = h_whdr;
00156 b->p_whdr = p_whdr;
00157
00158 p_whdr->lpData = p_buf;
00159 p_whdr->dwBufferLength = samples_per_buf * sizeof(int16);
00160 p_whdr->dwUser = 0L;
00161 p_whdr->dwFlags = 0L;
00162 p_whdr->dwLoops = 0L;
00163
00164 return 0;
00165 }
00166
00167
00168 static int32
00169 wavein_enqueue_buf(HWAVEIN h, LPWAVEHDR whdr)
00170 {
00171 int32 st;
00172
00173 if ((st = waveInPrepareHeader(h, whdr, sizeof(WAVEHDR))) != 0) {
00174 wavein_error("waveInPrepareHeader", st);
00175 return -1;
00176 }
00177 if ((st = waveInAddBuffer(h, whdr, sizeof(WAVEHDR))) != 0) {
00178 wavein_error("waveInAddBuffer", st);
00179 return -1;
00180 }
00181
00182 return 0;
00183 }
00184
00185
00186 static HWAVEIN
00187 wavein_open(int32 samples_per_sec, int32 bytes_per_sample)
00188 {
00189 WAVEFORMATEX wfmt;
00190 int32 st;
00191 HWAVEIN h;
00192
00193 if (bytes_per_sample != sizeof(int16)) {
00194 fprintf(stderr, "bytes/sample != %d\n", sizeof(int16));
00195 return NULL;
00196 }
00197
00198 wfmt.wFormatTag = WAVE_FORMAT_PCM;
00199 wfmt.nChannels = 1;
00200 wfmt.nSamplesPerSec = samples_per_sec;
00201 wfmt.nAvgBytesPerSec = samples_per_sec * bytes_per_sample;
00202 wfmt.nBlockAlign = bytes_per_sample;
00203 wfmt.wBitsPerSample = 8 * bytes_per_sample;
00204
00205
00206
00207 st = waveInOpen((LPHWAVEIN) & h, WAVE_MAPPER,
00208 (LPWAVEFORMATEX) & wfmt, (DWORD) 0L, 0L,
00209 (DWORD) CALLBACK_NULL);
00210 if (st != 0) {
00211 wavein_error("waveInOpen", st);
00212 return NULL;
00213 }
00214
00215 return h;
00216 }
00217
00218
00219 static int32
00220 wavein_close(ad_rec_t * r)
00221 {
00222 int32 i, st;
00223
00224
00225 for (i = 0; i < r->n_buf; i++) {
00226
00227
00228
00229 if (!(r->wi_buf[i].p_whdr->dwFlags & WHDR_PREPARED))
00230 continue;
00231 st = waveInUnprepareHeader(r->h_wavein,
00232 r->wi_buf[i].p_whdr, sizeof(WAVEHDR));
00233 if (st != 0) {
00234 wavein_error("waveInUnprepareHeader", st);
00235 return -1;
00236 }
00237 }
00238
00239
00240 for (i = 0; i < r->n_buf; i++)
00241 wavein_free_buf(&(r->wi_buf[i]));
00242 free(r->wi_buf);
00243
00244 if ((st = waveInClose(r->h_wavein)) != 0) {
00245 wavein_error("waveInClose", st);
00246 return -1;
00247 }
00248
00249 free(r);
00250
00251 return 0;
00252 }
00253
00254
00255 ad_rec_t *
00256 ad_open_sps_bufsize(int32 sps, int32 bufsize_msec)
00257 {
00258 ad_rec_t *r;
00259 int32 i, j;
00260 HWAVEIN h;
00261
00262 if ((h = wavein_open(sps, sizeof(int16))) == NULL)
00263 return NULL;
00264
00265 if ((r = (ad_rec_t *) malloc(sizeof(ad_rec_t))) == NULL) {
00266 fprintf(stderr, "malloc(%d) failed\n", sizeof(ad_rec_t));
00267 waveInClose(h);
00268 return NULL;
00269 }
00270
00271 r->n_buf = ((sps * bufsize_msec) / 1000) / WI_BUFSIZE;
00272 if (r->n_buf < DEFAULT_N_WI_BUF)
00273 r->n_buf = DEFAULT_N_WI_BUF;
00274 printf("Allocating %d buffers of %d samples each\n", r->n_buf,
00275 WI_BUFSIZE);
00276
00277 if ((r->wi_buf =
00278 (ad_wbuf_t *) calloc(r->n_buf, sizeof(ad_wbuf_t))) == NULL) {
00279 fprintf(stderr, "calloc(%d,%d) failed\n", r->n_buf,
00280 sizeof(ad_wbuf_t));
00281 free(r);
00282 waveInClose(h);
00283
00284 return NULL;
00285 }
00286 for (i = 0; i < r->n_buf; i++) {
00287 if (wavein_alloc_buf(&(r->wi_buf[i]), WI_BUFSIZE) < 0) {
00288 for (j = 0; j < i; j++)
00289 wavein_free_buf(&(r->wi_buf[j]));
00290 free(r->wi_buf);
00291 free(r);
00292 waveInClose(h);
00293
00294 return NULL;
00295 }
00296 }
00297
00298 r->h_wavein = h;
00299 r->opened = 1;
00300 r->recording = 0;
00301 r->curbuf = r->n_buf - 1;
00302 r->curlen = 0;
00303 r->lastbuf = r->curbuf;
00304 r->sps = sps;
00305 r->bps = sizeof(int16);
00306
00307 return r;
00308 }
00309
00310
00311 ad_rec_t *
00312 ad_open_dev(const char *dev, int32 sps)
00313 {
00314 return (ad_open_sps_bufsize
00315 (sps, WI_BUFSIZE * DEFAULT_N_WI_BUF * 1000 / sps));
00316 }
00317
00318
00319 ad_rec_t *
00320 ad_open_sps(int32 sps)
00321 {
00322 return (ad_open_sps_bufsize
00323 (sps, WI_BUFSIZE * DEFAULT_N_WI_BUF * 1000 / sps));
00324 }
00325
00326
00327 ad_rec_t *
00328 ad_open(void)
00329 {
00330 return (ad_open_sps(DEFAULT_SAMPLES_PER_SEC));
00331 }
00332
00333
00334 int32
00335 ad_close(ad_rec_t * r)
00336 {
00337 if (!r->opened)
00338 return AD_ERR_NOT_OPEN;
00339
00340 if (r->recording)
00341 if (ad_stop_rec(r) < 0)
00342 return AD_ERR_WAVE;
00343
00344 if (wavein_close(r) < 0)
00345 return AD_ERR_WAVE;
00346
00347 return 0;
00348 }
00349
00350
00351 int32
00352 ad_start_rec(ad_rec_t * r)
00353 {
00354 int32 i;
00355
00356 if ((!r->opened) || r->recording)
00357 return -1;
00358
00359 for (i = 0; i < r->n_buf; i++)
00360 if (wavein_enqueue_buf(r->h_wavein, r->wi_buf[i].p_whdr) < 0)
00361 return AD_ERR_WAVE;
00362 r->curbuf = r->n_buf - 1;
00363 r->curlen = 0;
00364
00365 if (waveInStart(r->h_wavein) != 0)
00366 return AD_ERR_WAVE;
00367
00368 r->recording = 1;
00369
00370 return 0;
00371 }
00372
00373
00374 int32
00375 ad_stop_rec(ad_rec_t * r)
00376 {
00377 int32 i, st;
00378
00379 if ((!r->opened) || (!r->recording))
00380 return -1;
00381
00382 if (waveInStop(r->h_wavein) != 0)
00383 return AD_ERR_WAVE;
00384
00385 if ((st = waveInReset(r->h_wavein)) != 0) {
00386 wavein_error("waveInReset", st);
00387 return AD_ERR_WAVE;
00388 }
00389
00390
00391 for (i = 0; i < r->n_buf; i++)
00392 while (!(r->wi_buf[i].p_whdr->dwFlags & WHDR_DONE));
00393
00394 if ((r->lastbuf = r->curbuf - 1) < 0)
00395 r->lastbuf = r->n_buf - 1;
00396
00397 r->recording = 0;
00398
00399 return 0;
00400 }
00401
00402
00403 int32
00404 ad_read(ad_rec_t * r, int16 * buf, int32 max)
00405 {
00406 int32 t, st, len;
00407 LPWAVEHDR whdr;
00408 int16 *sysbufp;
00409
00410 if (!r->opened)
00411 return AD_ERR_NOT_OPEN;
00412
00413
00414 if ((!r->recording) && (r->curbuf == r->lastbuf)
00415 && (r->curlen == 0))
00416 return AD_EOF;
00417
00418 len = 0;
00419 while (max > 0) {
00420
00421 if (r->curlen == 0) {
00422
00423 t = r->curbuf + 1;
00424 if (t >= r->n_buf)
00425 t = 0;
00426
00427 if (!(r->wi_buf[t].p_whdr->dwFlags & WHDR_DONE))
00428 return len;
00429
00430 r->curbuf = t;
00431 r->curlen = r->wi_buf[t].p_whdr->dwBytesRecorded >> 1;
00432 r->curoff = 0;
00433 }
00434
00435
00436 whdr = r->wi_buf[r->curbuf].p_whdr;
00437 t = (max < r->curlen) ? max : r->curlen;
00438
00439 if (t > 0) {
00440 sysbufp = (int16 *) (whdr->lpData);
00441 memcpy(buf, sysbufp + r->curoff, t * sizeof(int16));
00442
00443 buf += t;
00444 max -= t;
00445 r->curoff += t;
00446 r->curlen -= t;
00447 len += t;
00448 }
00449
00450
00451 if (r->curlen == 0) {
00452 if (r->recording) {
00453
00454 st = waveInUnprepareHeader(r->h_wavein,
00455 whdr, sizeof(WAVEHDR));
00456 if (st != 0) {
00457 wavein_error("waveInUnprepareHeader", st);
00458 return AD_ERR_WAVE;
00459 }
00460
00461 if (wavein_enqueue_buf(r->h_wavein, whdr) < 0)
00462 return AD_ERR_WAVE;
00463
00464 }
00465 else if (r->curbuf == r->lastbuf) {
00466 return len;
00467 }
00468 }
00469 }
00470
00471 return len;
00472 }