Edinburgh Speech Tools 2.4-release
os2audio.cc
1/* Check all of ./speech_tools and ./festival for reference to win32audio, */
2/* and add the equivalent for the os2audio module. You will need -los2me */
3/* to compile this os2audio module. */
4
5
6/* OS/2 16bit realtime DART Audio support for Festival */
7/* Samuel Audet <guardia@cam.org> */
8/* DeviceID is setup in here. Can be used as an external variable! */
9
10#ifdef SUPPORT_OS2AUDIO
11
12#include "EST_cutils.h"
13
14#include "EST_Wave.h"
15
16#include "EST_Option.h"
17
18#include "audioP.h"
19
20#include "EST_io_aux.h"
21
22#include "EST_unix.h"
23
24int os2audio_supported = TRUE;
25
26#define INCL_OS2MM
27
28#define INCL_DOS
29
30#include <os2.h>
31
32#include <os2me.h>
33
34
35USHORT DeviceID = 0; /* 0 = default sound device, 1 = 1st sound device, etc. */
36
37/* new stuff */
38#define MIX_BUFFER_EOS 1
39
40
41#define NUM_BUFFERS 8 /* Number of audio buffer usable */
42static ULONG ulMCIBuffers; /* warning, minimum 2 */
43
44static MCI_AMP_OPEN_PARMS maop;
45static MCI_MIXSETUP_PARMS mmp;
46static MCI_BUFFER_PARMS mbp;
47static MCI_GENERIC_PARMS mgp = {0};
48static MCI_MIX_BUFFER MixBuffers[NUM_BUFFERS];
49static unsigned char *wave, *startwave, *endwave;
50static ULONG sizewave;
51
52static HEV dataplayed;
53
54
55static void MciError(ULONG ulError)
56{
57 unsigned char buffer[128];
58 unsigned char string[128];
59 ULONG rc;
60
61 rc = mciGetErrorString(ulError, buffer, sizeof(buffer));
62
63 if (rc == MCIERR_SUCCESS)
64 sprintf(string,"MCI Error %d: %s",ULONG_LOWD(ulError),buffer);
65 else
66 sprintf(string,"MCI Error %d: Cannot query error message.",ULONG_LOWD(rc));
67
68 cerr << string << endl;
69}
70
71
72static LONG APIENTRY MyEvent(ULONG ulStatus, PMCI_MIX_BUFFER PlayedBuffer, ULONG ulFlags)
73{
74 if(PlayedBuffer->ulFlags == MIX_BUFFER_EOS)
75 DosPostEventSem(dataplayed);
76 else
77 switch(ulFlags)
78 {
79 case MIX_STREAM_ERROR | MIX_WRITE_COMPLETE: /* error occur in device */
80
81 if ( ulStatus == ERROR_DEVICE_UNDERRUN)
82 /* Write buffers to rekick off the amp mixer. */
83 mmp.pmixWrite( mmp.ulMixHandle,
84 MixBuffers,
85 ulMCIBuffers );
86 break;
87
88 case MIX_WRITE_COMPLETE: /* for playback */
89
90 if(wave < endwave)
91 {
92 /* copy new data in the played buffer */
93 if(wave + PlayedBuffer->ulBufferLength >= endwave)
94 {
95 PlayedBuffer->ulFlags = MIX_BUFFER_EOS; /* set end of stream */
96 PlayedBuffer->ulBufferLength = (ULONG) (endwave - wave);
97 }
98 memcpy(PlayedBuffer->pBuffer, wave, PlayedBuffer->ulBufferLength);
99 wave += PlayedBuffer->ulBufferLength;
100
101 mmp.pmixWrite( mmp.ulMixHandle,
102 PlayedBuffer /* contains new data */,
103 1 );
104 }
105
106 break;
107
108 } /* end switch */
109
110 return( TRUE );
111
112} /* end MyEvent */
113
114
115int play_os2audio_wave(EST_Wave &inwave, EST_Option &al)
116{
117 ULONG i,rc;
118
119 startwave = (unsigned char *) inwave.values().memory();
120 sizewave = inwave.num_samples()*sizeof(short)*inwave.num_channels();
121 endwave = startwave + sizewave;
122 wave = startwave;
123
124 /* open the mixer device */
125 memset (&maop, 0, sizeof(maop));
126 maop.usDeviceID = 0;
127 maop.pszDeviceType = (PSZ) MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX, DeviceID);
128
129 rc = mciSendCommand(0,
130 MCI_OPEN,
131 MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
132 &maop,
133 0);
134
135 if (rc != MCIERR_SUCCESS)
136 {
137 MciError(rc);
138 return(-1);
139 }
140
141 /* Set the MCI_MIXSETUP_PARMS data structure to match the audio stream. */
142
143 memset(&mmp, 0, sizeof(mmp));
144
145 mmp.ulBitsPerSample = 16;
146 mmp.ulFormatTag = MCI_WAVE_FORMAT_PCM;
147 mmp.ulSamplesPerSec = inwave.sample_rate();
148 mmp.ulChannels = inwave.num_channels();
149
150 /* Setup the mixer for playback of wave data */
151 mmp.ulFormatMode = MCI_PLAY;
152 mmp.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
153 mmp.pmixEvent = MyEvent;
154
155 rc = mciSendCommand( maop.usDeviceID,
156 MCI_MIXSETUP,
157 MCI_WAIT | MCI_MIXSETUP_INIT,
158 &mmp,
159 0 );
160
161 if ( rc != MCIERR_SUCCESS )
162 {
163 MciError(rc);
164 return(-1);
165 }
166
167 /* Set up the BufferParms data structure and allocate
168 * device buffers from the Amp-Mixer */
169
170 ulMCIBuffers = NUM_BUFFERS;
171 mbp.ulNumBuffers = ulMCIBuffers;
172 mbp.ulBufferSize = mmp.ulBufferSize;
173 memset(MixBuffers, 0, sizeof(MixBuffers[0])*NUM_BUFFERS);
174 mbp.pBufList = MixBuffers;
175
176 rc = mciSendCommand( maop.usDeviceID,
177 MCI_BUFFER,
178 MCI_WAIT | MCI_ALLOCATE_MEMORY,
179 (PVOID) &mbp,
180 0 );
181
182 if ( ULONG_LOWD(rc) != MCIERR_SUCCESS )
183 {
184 MciError(rc);
185 return(-1);
186 }
187
188 ulMCIBuffers = mbp.ulNumBuffers; /* never know! */
189
190 /* Fill all device buffers with data from the wave stream. */
191
192 for(i = 0; i < ulMCIBuffers; i++)
193 {
194 if(wave < endwave)
195 {
196 MixBuffers[i].ulFlags = 0;
197 MixBuffers[i].ulBufferLength = mbp.ulBufferSize;
198 if(wave + MixBuffers[i].ulBufferLength >= endwave)
199 {
200 MixBuffers[i].ulFlags = MIX_BUFFER_EOS; /* set end of stream */
201 MixBuffers[i].ulBufferLength = (ULONG) (endwave - wave);
202 }
203 memcpy(MixBuffers[i].pBuffer, wave, MixBuffers[i].ulBufferLength);
204 wave += MixBuffers[i].ulBufferLength;
205 }
206 }
207
208 /* Create a semaphore to know when data has been played by the DART thread */
209 DosCreateEventSem(NULL,&dataplayed,0,FALSE);
210
211 /* Write buffers to kick off the amp mixer. */
212 rc = mmp.pmixWrite( mmp.ulMixHandle,
213 MixBuffers,
214 ulMCIBuffers );
215
216 if ( rc != MCIERR_SUCCESS )
217 {
218 MciError(rc);
219 return(-1);
220 }
221
222 DosWaitEventSem(dataplayed, -1);
223 DosCloseEventSem(dataplayed);
224
225 rc = mciSendCommand( maop.usDeviceID,
226 MCI_BUFFER,
227 MCI_WAIT | MCI_DEALLOCATE_MEMORY,
228 &mbp,
229 0 );
230
231 if ( rc != MCIERR_SUCCESS )
232 {
233 MciError(rc);
234 return(-1);
235 }
236
237 rc = mciSendCommand( maop.usDeviceID,
238 MCI_CLOSE,
239 MCI_WAIT ,
240 &mgp,
241 0 );
242
243 if ( rc != MCIERR_SUCCESS )
244 {
245 MciError(rc);
246 return(-1);
247 }
248
249 return TRUE;
250}
251
252#else
253
254# include "EST_Wave.h"
255# include "EST_Option.h"
256
257int os2audio_supported = FALSE;
258
259int play_os2audio_wave(EST_Wave &inwave, EST_Option &al)
260{
261 (void)inwave;
262 (void)al;
263 cerr << "OS/2 16bit realtime DART playback not supported." << endl;
264 return -1;
265}
266
267#endif
268
269
const T * memory() const
Definition: EST_TVector.h:241
int num_channels() const
return the number of channels in the waveform
Definition: EST_Wave.h:145
int sample_rate() const
return the sampling rate (frequency)
Definition: EST_Wave.h:147
int num_samples() const
return the number of samples in the waveform
Definition: EST_Wave.h:143