1 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* ====================================================================
3 * Copyright (c) 1999-2001 Carnegie Mellon University. All rights
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
18 * This work was supported in part by funding from the Defense Advanced
19 * Research Projects Agency and the National Science Foundation of the
20 * United States of America, and the CMU Sphinx Speech Consortium.
22 * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
23 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
26 * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * ====================================================================
41 * 17-Apr-98 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
42 * Added ad_open_play_sps(), and made ad_open_play() call it.
44 * 10-Jun-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
45 * Added ad_play_t type to all calls.
47 * 03-Jun-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
58 #include "sphinxbase/prim_type.h"
59 #include "sphinxbase/ad.h"
62 #define WO_BUFSIZE 3200 /* Samples/buf */
63 #define N_WO_BUF 2 /* #Playback bufs */
65 /* Silvio Moioli: using OutputDebugStringW instead of OutputDebugString */
67 #include "ckd_alloc.h"
69 waveout_error(char *src, int32 ret)
75 waveOutGetErrorText(ret, errbuf, sizeof(errbuf));
76 len = mbstowcs(NULL, errbuf, 0) + 1;
77 werrbuf = ckd_calloc(len, sizeof(*werrbuf));
78 mbstowcs(werrbuf, errbuf, len);
80 OutputDebugStringW(werrbuf);
85 waveout_error(char *src, int32 ret)
89 waveOutGetErrorText(ret, errbuf, sizeof(errbuf));
90 fprintf(stderr, "%s error %d: %s\n", src, ret, errbuf);
96 waveout_free_buf(ad_wbuf_t * b)
98 GlobalUnlock(b->h_whdr);
99 GlobalFree(b->h_whdr);
100 GlobalUnlock(b->h_buf);
101 GlobalFree(b->h_buf);
106 waveout_alloc_buf(ad_wbuf_t * b, int32 samples_per_buf)
113 /* Allocate data buffer */
115 GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
116 samples_per_buf * sizeof(int16));
118 fprintf(stderr, "GlobalAlloc failed\n");
121 if ((p_buf = GlobalLock(h_buf)) == NULL) {
123 fprintf(stderr, "GlobalLock failed\n");
127 /* Allocate WAVEHDR structure */
128 h_whdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR));
129 if (h_whdr == NULL) {
133 fprintf(stderr, "GlobalAlloc failed\n");
136 if ((p_whdr = GlobalLock(h_whdr)) == NULL) {
141 fprintf(stderr, "GlobalLock failed\n");
150 p_whdr->lpData = p_buf;
151 p_whdr->dwBufferLength = samples_per_buf * sizeof(int16);
153 p_whdr->dwFlags = 0L;
154 p_whdr->dwLoops = 0L;
161 waveout_enqueue_buf(HWAVEOUT h, LPWAVEHDR whdr)
165 if ((st = waveOutPrepareHeader(h, whdr, sizeof(WAVEHDR))) != 0) {
166 waveout_error("waveOutPrepareHeader", st);
170 if ((st = waveOutWrite(h, whdr, sizeof(WAVEHDR))) != 0) {
171 waveout_error("waveOutWrite", st);
180 waveout_open(int32 samples_per_sec, int32 bytes_per_sample)
186 if (bytes_per_sample != sizeof(int16)) {
187 fprintf(stderr, "bytes/sample != %d\n", sizeof(int16));
191 wfmt.wFormatTag = WAVE_FORMAT_PCM;
193 wfmt.nSamplesPerSec = samples_per_sec;
194 wfmt.nAvgBytesPerSec = samples_per_sec * bytes_per_sample;
195 wfmt.nBlockAlign = bytes_per_sample;
196 wfmt.wBitsPerSample = 8 * bytes_per_sample;
199 /* There should be a check here for a device of the desired type; later... */
201 st = waveOutOpen((LPHWAVEOUT) & h, WAVE_MAPPER,
202 (LPWAVEFORMATEX) & wfmt, (DWORD) 0L, 0L,
203 (DWORD) CALLBACK_NULL);
205 waveout_error("waveOutOpen", st);
214 waveout_mem_cleanup(ad_play_t * p, int32 n_buf)
218 for (i = 0; i < n_buf; i++)
219 waveout_free_buf(&(p->wo_buf[i]));
228 waveout_close(ad_play_t * p)
232 waveout_mem_cleanup(p, N_WO_BUF);
234 if ((st = waveOutClose(p->h_waveout)) != 0) {
235 waveout_error("waveOutClose", st);
246 ad_open_play_sps(int32 sps)
252 if ((h = waveout_open(sps, sizeof(int16))) == NULL)
255 if ((p = (ad_play_t *) calloc(1, sizeof(ad_play_t))) == NULL) {
256 fprintf(stderr, "calloc(1,%d) failed\n", sizeof(ad_play_t));
261 (ad_wbuf_t *) calloc(N_WO_BUF, sizeof(ad_wbuf_t))) == NULL) {
262 fprintf(stderr, "calloc(%d,%d) failed\n", N_WO_BUF,
269 if ((p->busy = (char *) calloc(N_WO_BUF, sizeof(char))) == NULL) {
270 fprintf(stderr, "calloc(%d,%d) failed\n", N_WO_BUF, sizeof(char));
271 waveout_mem_cleanup(p, 0);
277 for (i = 0; i < N_WO_BUF; i++) {
278 if (waveout_alloc_buf(&(p->wo_buf[i]), WO_BUFSIZE) < 0) {
279 waveout_mem_cleanup(p, i);
292 p->bps = sizeof(int16); /* HACK!! Hardwired value for bytes/sec */
301 return (ad_open_play_sps(DEFAULT_SAMPLES_PER_SEC));
306 ad_close_play(ad_play_t * p)
312 if (ad_stop_play(p) < 0)
315 if (waveout_close(p) < 0)
323 ad_start_play(ad_play_t * p)
327 if ((!p->opened) || p->playing)
330 for (i = 0; i < N_WO_BUF; i++)
340 ad_stop_play(ad_play_t * p)
345 if ((!p->opened) || (!p->playing))
349 whdr->dwUser = (plen <= 0) ? 1 : 0;
352 /* Wait for all buffers to be emptied and unprepare them */
353 for (i = 0; i < N_WO_BUF; i++) {
354 whdr = p->wo_buf[i].p_whdr;
356 while (p->busy[i] && (!(whdr->dwFlags & WHDR_DONE)))
359 st = waveOutUnprepareHeader(p->h_waveout, whdr, sizeof(WAVEHDR));
361 waveout_error("waveOutUnprepareHeader", st);
373 ad_write(ad_play_t * p, int16 * buf, int32 size)
378 if ((!p->opened) || (!p->playing))
383 for (i = 0; (i < N_WO_BUF) && (size > 0); i++) {
384 whdr = p->wo_buf[p->nxtbuf].p_whdr;
386 if (p->busy[p->nxtbuf]) {
387 if (!(whdr->dwFlags & WHDR_DONE))
390 st = waveOutUnprepareHeader(p->h_waveout, whdr,
393 waveout_error("waveOutUnprepareHeader", st);
397 p->busy[p->nxtbuf] = 0;
400 k = (size > WO_BUFSIZE) ? WO_BUFSIZE : size;
402 whdr->dwBufferLength = k * sizeof(int16);
403 memcpy(whdr->lpData, (LPSTR) buf, k * sizeof(int16));
405 if (waveout_enqueue_buf(p->h_waveout, whdr) < 0)
412 p->busy[(p->nxtbuf)++] = 1;
413 if (p->nxtbuf >= N_WO_BUF)