SphinxBase 0.6
|
00001 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */ 00002 /* ==================================================================== 00003 * Copyright (c) 1999-2001 Carnegie Mellon University. All rights 00004 * reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * 2. Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in 00015 * the documentation and/or other materials provided with the 00016 * distribution. 00017 * 00018 * This work was supported in part by funding from the Defense Advanced 00019 * Research Projects Agency and the National Science Foundation of the 00020 * United States of America, and the CMU Sphinx Speech Consortium. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND 00023 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 00024 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00025 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY 00026 * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00027 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00028 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00029 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00030 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00031 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00032 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 * 00034 * ==================================================================== 00035 * 00036 */ 00037 00038 /* 00039 * HISTORY 00040 * 00041 * 17-Apr-98 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University 00042 * Added ad_open_play_sps(), and made ad_open_play() call it. 00043 * 00044 * 10-Jun-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University 00045 * Added ad_play_t type to all calls. 00046 * 00047 * 03-Jun-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University 00048 * Created. 00049 */ 00050 00051 00052 #include <windows.h> 00053 #include <mmsystem.h> 00054 #include <stdio.h> 00055 #include <stdlib.h> 00056 #include <string.h> 00057 00058 #include "sphinxbase/prim_type.h" 00059 #include "sphinxbase/ad.h" 00060 00061 00062 #define WO_BUFSIZE 3200 /* Samples/buf */ 00063 #define N_WO_BUF 2 /* #Playback bufs */ 00064 00065 /* Silvio Moioli: using OutputDebugStringW instead of OutputDebugString */ 00066 #ifdef _WIN32_WCE 00067 #include "ckd_alloc.h" 00068 static void 00069 waveout_error(char *src, int32 ret) 00070 { 00071 TCHAR errbuf[512]; 00072 wchar_t* werrbuf; 00073 size_t len; 00074 00075 waveOutGetErrorText(ret, errbuf, sizeof(errbuf)); 00076 len = mbstowcs(NULL, errbuf, 0) + 1; 00077 werrbuf = ckd_calloc(len, sizeof(*werrbuf)); 00078 mbstowcs(werrbuf, errbuf, len); 00079 00080 OutputDebugStringW(werrbuf); 00081 } 00082 00083 #else 00084 static void 00085 waveout_error(char *src, int32 ret) 00086 { 00087 char errbuf[1024]; 00088 00089 waveOutGetErrorText(ret, errbuf, sizeof(errbuf)); 00090 fprintf(stderr, "%s error %d: %s\n", src, ret, errbuf); 00091 } 00092 #endif 00093 00094 00095 static void 00096 waveout_free_buf(ad_wbuf_t * b) 00097 { 00098 GlobalUnlock(b->h_whdr); 00099 GlobalFree(b->h_whdr); 00100 GlobalUnlock(b->h_buf); 00101 GlobalFree(b->h_buf); 00102 } 00103 00104 00105 static int32 00106 waveout_alloc_buf(ad_wbuf_t * b, int32 samples_per_buf) 00107 { 00108 HGLOBAL h_buf; 00109 LPSTR p_buf; 00110 HGLOBAL h_whdr; 00111 LPWAVEHDR p_whdr; 00112 00113 /* Allocate data buffer */ 00114 h_buf = 00115 GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, 00116 samples_per_buf * sizeof(int16)); 00117 if (!h_buf) { 00118 fprintf(stderr, "GlobalAlloc failed\n"); 00119 return -1; 00120 } 00121 if ((p_buf = GlobalLock(h_buf)) == NULL) { 00122 GlobalFree(h_buf); 00123 fprintf(stderr, "GlobalLock failed\n"); 00124 return -1; 00125 } 00126 00127 /* Allocate WAVEHDR structure */ 00128 h_whdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR)); 00129 if (h_whdr == NULL) { 00130 GlobalUnlock(h_buf); 00131 GlobalFree(h_buf); 00132 00133 fprintf(stderr, "GlobalAlloc failed\n"); 00134 return -1; 00135 } 00136 if ((p_whdr = GlobalLock(h_whdr)) == NULL) { 00137 GlobalUnlock(h_buf); 00138 GlobalFree(h_buf); 00139 GlobalFree(h_whdr); 00140 00141 fprintf(stderr, "GlobalLock failed\n"); 00142 return -1; 00143 } 00144 00145 b->h_buf = h_buf; 00146 b->p_buf = p_buf; 00147 b->h_whdr = h_whdr; 00148 b->p_whdr = p_whdr; 00149 00150 p_whdr->lpData = p_buf; 00151 p_whdr->dwBufferLength = samples_per_buf * sizeof(int16); 00152 p_whdr->dwUser = 0L; 00153 p_whdr->dwFlags = 0L; 00154 p_whdr->dwLoops = 0L; 00155 00156 return 0; 00157 } 00158 00159 00160 static int32 00161 waveout_enqueue_buf(HWAVEOUT h, LPWAVEHDR whdr) 00162 { 00163 int32 st; 00164 00165 if ((st = waveOutPrepareHeader(h, whdr, sizeof(WAVEHDR))) != 0) { 00166 waveout_error("waveOutPrepareHeader", st); 00167 return -1; 00168 } 00169 00170 if ((st = waveOutWrite(h, whdr, sizeof(WAVEHDR))) != 0) { 00171 waveout_error("waveOutWrite", st); 00172 return -1; 00173 } 00174 00175 return 0; 00176 } 00177 00178 00179 static HWAVEOUT 00180 waveout_open(int32 samples_per_sec, int32 bytes_per_sample) 00181 { 00182 WAVEFORMATEX wfmt; 00183 int32 st; 00184 HWAVEOUT h; 00185 00186 if (bytes_per_sample != sizeof(int16)) { 00187 fprintf(stderr, "bytes/sample != %d\n", sizeof(int16)); 00188 return NULL; 00189 } 00190 00191 wfmt.wFormatTag = WAVE_FORMAT_PCM; 00192 wfmt.nChannels = 1; 00193 wfmt.nSamplesPerSec = samples_per_sec; 00194 wfmt.nAvgBytesPerSec = samples_per_sec * bytes_per_sample; 00195 wfmt.nBlockAlign = bytes_per_sample; 00196 wfmt.wBitsPerSample = 8 * bytes_per_sample; 00197 wfmt.cbSize = 0; 00198 00199 /* There should be a check here for a device of the desired type; later... */ 00200 00201 st = waveOutOpen((LPHWAVEOUT) & h, WAVE_MAPPER, 00202 (LPWAVEFORMATEX) & wfmt, (DWORD) 0L, 0L, 00203 (DWORD) CALLBACK_NULL); 00204 if (st != 0) { 00205 waveout_error("waveOutOpen", st); 00206 return NULL; 00207 } 00208 00209 return h; 00210 } 00211 00212 00213 static void 00214 waveout_mem_cleanup(ad_play_t * p, int32 n_buf) 00215 { 00216 int32 i; 00217 00218 for (i = 0; i < n_buf; i++) 00219 waveout_free_buf(&(p->wo_buf[i])); 00220 if (p->wo_buf) 00221 free(p->wo_buf); 00222 if (p->busy) 00223 free(p->busy); 00224 } 00225 00226 00227 static int32 00228 waveout_close(ad_play_t * p) 00229 { 00230 int32 st; 00231 00232 waveout_mem_cleanup(p, N_WO_BUF); 00233 00234 if ((st = waveOutClose(p->h_waveout)) != 0) { 00235 waveout_error("waveOutClose", st); 00236 return -1; 00237 } 00238 00239 free(p); 00240 00241 return 0; 00242 } 00243 00244 00245 ad_play_t * 00246 ad_open_play_sps(int32 sps) 00247 { 00248 ad_play_t *p; 00249 int32 i; 00250 HWAVEOUT h; 00251 00252 if ((h = waveout_open(sps, sizeof(int16))) == NULL) 00253 return NULL; 00254 00255 if ((p = (ad_play_t *) calloc(1, sizeof(ad_play_t))) == NULL) { 00256 fprintf(stderr, "calloc(1,%d) failed\n", sizeof(ad_play_t)); 00257 waveOutClose(h); 00258 return NULL; 00259 } 00260 if ((p->wo_buf = 00261 (ad_wbuf_t *) calloc(N_WO_BUF, sizeof(ad_wbuf_t))) == NULL) { 00262 fprintf(stderr, "calloc(%d,%d) failed\n", N_WO_BUF, 00263 sizeof(ad_wbuf_t)); 00264 free(p); 00265 waveOutClose(h); 00266 00267 return NULL; 00268 } 00269 if ((p->busy = (char *) calloc(N_WO_BUF, sizeof(char))) == NULL) { 00270 fprintf(stderr, "calloc(%d,%d) failed\n", N_WO_BUF, sizeof(char)); 00271 waveout_mem_cleanup(p, 0); 00272 free(p); 00273 waveOutClose(h); 00274 00275 return NULL; 00276 } 00277 for (i = 0; i < N_WO_BUF; i++) { 00278 if (waveout_alloc_buf(&(p->wo_buf[i]), WO_BUFSIZE) < 0) { 00279 waveout_mem_cleanup(p, i); 00280 free(p); 00281 waveOutClose(h); 00282 00283 return NULL; 00284 } 00285 } 00286 00287 p->h_waveout = h; 00288 p->playing = 0; 00289 p->opened = 1; 00290 p->nxtbuf = 0; 00291 p->sps = sps; 00292 p->bps = sizeof(int16); /* HACK!! Hardwired value for bytes/sec */ 00293 00294 return p; 00295 } 00296 00297 00298 ad_play_t * 00299 ad_open_play(void) 00300 { 00301 return (ad_open_play_sps(DEFAULT_SAMPLES_PER_SEC)); 00302 } 00303 00304 00305 int32 00306 ad_close_play(ad_play_t * p) 00307 { 00308 if (!p->opened) 00309 return 0; 00310 00311 if (p->playing) 00312 if (ad_stop_play(p) < 0) 00313 return -1; 00314 00315 if (waveout_close(p) < 0) 00316 return -1; 00317 00318 return 0; 00319 } 00320 00321 00322 int32 00323 ad_start_play(ad_play_t * p) 00324 { 00325 int32 i; 00326 00327 if ((!p->opened) || p->playing) 00328 return -1; 00329 00330 for (i = 0; i < N_WO_BUF; i++) 00331 p->busy[i] = 0; 00332 p->nxtbuf = 0; 00333 p->playing = 1; 00334 00335 return 0; 00336 } 00337 00338 00339 int32 00340 ad_stop_play(ad_play_t * p) 00341 { 00342 int32 i, st; 00343 LPWAVEHDR whdr; 00344 00345 if ((!p->opened) || (!p->playing)) 00346 return -1; 00347 00348 #if 0 00349 whdr->dwUser = (plen <= 0) ? 1 : 0; 00350 #endif 00351 00352 /* Wait for all buffers to be emptied and unprepare them */ 00353 for (i = 0; i < N_WO_BUF; i++) { 00354 whdr = p->wo_buf[i].p_whdr; 00355 00356 while (p->busy[i] && (!(whdr->dwFlags & WHDR_DONE))) 00357 Sleep(100); 00358 00359 st = waveOutUnprepareHeader(p->h_waveout, whdr, sizeof(WAVEHDR)); 00360 if (st != 0) { 00361 waveout_error("waveOutUnprepareHeader", st); 00362 return -1; 00363 } 00364 00365 p->busy[i] = 0; 00366 } 00367 00368 return 0; 00369 } 00370 00371 00372 int32 00373 ad_write(ad_play_t * p, int16 * buf, int32 size) 00374 { 00375 int32 i, k, len, st; 00376 LPWAVEHDR whdr; 00377 00378 if ((!p->opened) || (!p->playing)) 00379 return -1; 00380 00381 len = 0; 00382 00383 for (i = 0; (i < N_WO_BUF) && (size > 0); i++) { 00384 whdr = p->wo_buf[p->nxtbuf].p_whdr; 00385 00386 if (p->busy[p->nxtbuf]) { 00387 if (!(whdr->dwFlags & WHDR_DONE)) 00388 return len; 00389 00390 st = waveOutUnprepareHeader(p->h_waveout, whdr, 00391 sizeof(WAVEHDR)); 00392 if (st != 0) { 00393 waveout_error("waveOutUnprepareHeader", st); 00394 return -1; 00395 } 00396 00397 p->busy[p->nxtbuf] = 0; 00398 } 00399 00400 k = (size > WO_BUFSIZE) ? WO_BUFSIZE : size; 00401 00402 whdr->dwBufferLength = k * sizeof(int16); 00403 memcpy(whdr->lpData, (LPSTR) buf, k * sizeof(int16)); 00404 00405 if (waveout_enqueue_buf(p->h_waveout, whdr) < 0) 00406 return -1; 00407 00408 buf += k; 00409 size -= k; 00410 len += k; 00411 00412 p->busy[(p->nxtbuf)++] = 1; 00413 if (p->nxtbuf >= N_WO_BUF) 00414 p->nxtbuf = 0; 00415 } 00416 00417 return len; 00418 }