Edinburgh Speech Tools 2.4-release
 
Loading...
Searching...
No Matches
gen_audio.cc
1/*************************************************************************/
2/* */
3/* Centre for Speech Technology Research */
4/* University of Edinburgh, UK */
5/* Copyright (c) 1995,1996 */
6/* All Rights Reserved. */
7/* */
8/* Permission is hereby granted, free of charge, to use and distribute */
9/* this software and its documentation without restriction, including */
10/* without limitation the rights to use, copy, modify, merge, publish, */
11/* distribute, sublicense, and/or sell copies of this work, and to */
12/* permit persons to whom this work is furnished to do so, subject to */
13/* the following conditions: */
14/* 1. The code must retain the above copyright notice, this list of */
15/* conditions and the following disclaimer. */
16/* 2. Any modifications must be clearly marked as such. */
17/* 3. Original authors' names are not deleted. */
18/* 4. The authors' names are not used to endorse or promote products */
19/* derived from this software without specific prior written */
20/* permission. */
21/* */
22/* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23/* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24/* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25/* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26/* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27/* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28/* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29/* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30/* THIS SOFTWARE. */
31/* */
32/*************************************************************************/
33/* Author : Paul Taylor */
34/* Date : March 95 */
35/*-----------------------------------------------------------------------*/
36/* Generalised playback function */
37/* */
38/*=======================================================================*/
39
40#include <cstdlib>
41#include <iostream>
42#include <cstring>
43#include <cmath>
44#include <fcntl.h>
45#include "EST_system.h"
46#include "EST_socket.h"
47#include "EST_Option.h"
48#include "EST_Wave.h"
49#include "EST_io_aux.h"
50#include "audioP.h"
51#include "EST_audio.h"
52#include "EST_wave_aux.h"
53
54static int play_sunau_wave(EST_Wave &inwave, EST_Option &al);
55static int play_socket_wave(EST_Wave &inwave, EST_Option &al);
56static int play_aucomm_wave(EST_Wave &inwave, EST_Option &al);
57
58static int record_sunau_wave(EST_Wave &wave, EST_Option &al);
59
60int play_wave(EST_Wave &inwave, EST_Option &al)
61{
62 EST_String protocol;
63 EST_Wave wtmp;
64 EST_Wave *toplay;
65 char *quality;
66 char *sr;
67
68 if ((sr = getenv("NA_PLAY_HOST")) != NULL)
69 if (!al.present("-display"))
70 al.add_item("-display", sr);
71
72 if ((quality = getenv("NA_PLAY_QUALITY")) != NULL)
73 if (!al.present("-quality"))
74 al.add_item("-quality", quality);
75
76 if (al.present("-p"))
77 protocol = al.val("-p");
78 else if ((sr=getenv("NA_PLAY_PROTOCOL")) != NULL)
79 protocol = sr;
80 else if (protocol == "")
81 {
82 if (nas_supported)
83 protocol = "netaudio"; // the default protocol
84 else if (pulse_supported)
85 protocol = "pulseaudio";
86 else if (esd_supported)
87 protocol = "esdaudio";
88 else if (sun16_supported)
89 protocol = "sun16audio";
90 else if (freebsd16_supported)
91 protocol = "freebsd16audio";
92 else if (linux16_supported)
93 protocol = "linux16audio";
94 else if (irix_supported)
95 protocol = "irixaudio";
96 else if (macosx_supported)
97 protocol = "macosxaudio";
98 else if (win32audio_supported)
99 protocol = "win32audio";
100 else if (mplayer_supported)
101 protocol = "mplayeraudio";
102 else
103 protocol = "sunaudio";
104 }
105
106 // OS X can handle multichannel audio, don't know about other systems.
107 if (inwave.num_channels() > 1 && upcase(protocol) != "MACOSXAUDIO" )
108 {
109 wave_combine_channels(wtmp,inwave);
110 toplay = &wtmp;
111 }
112 else
113 toplay = &inwave;
114
115 if (upcase(protocol) == "NETAUDIO")
116 return play_nas_wave(*toplay,al);
117 else if (upcase(protocol) == "PULSEAUDIO")
118 return play_pulse_wave(*toplay,al);
119 else if (upcase(protocol) == "ESDAUDIO")
120 return play_esd_wave(*toplay,al);
121 else if (upcase(protocol) == "SUNAUDIO")
122 return play_sunau_wave(*toplay,al);
123 else if (upcase(protocol) == "SUN16AUDIO")
124 return play_sun16_wave(*toplay,al);
125 else if ((upcase(protocol) == "FREEBSD16AUDIO") ||
126 (upcase(protocol) == "LINUX16AUDIO"))
127 return play_linux_wave(*toplay,al);
128 else if (upcase(protocol) == "IRIXAUDIO")
129 return play_irix_wave(*toplay,al);
130 else if (upcase(protocol) == "MACOSXAUDIO")
131 return play_macosx_wave(*toplay,al);
132 else if (upcase(protocol) == "MPLAYERAUDIO")
133 return play_mplayer_wave(*toplay,al);
134 else if (upcase(protocol) == "WIN32AUDIO")
135 return play_win32audio_wave(*toplay,al);
136 else if (upcase(protocol) == "AUDIO_COMMAND")
137 return play_aucomm_wave(*toplay,al);
138 else if (upcase(protocol) == "SOCKET")
139 return play_socket_wave(*toplay,al);
140 else
141 {
142 cerr << "Unknown audio server protocol " << protocol << endl;
143 return -1;
144 }
145}
146
147static int play_socket_wave(EST_Wave &inwave, EST_Option &al)
148{
149 // Send inwave down the given fd (a socket)
150 SOCKET_FD fd;
151 EST_String otype;
152 EST_String tmpfile = make_tmp_filename();
153
154 if (al.present("socket_fd"))
155 fd = al.ival("socket_fd");
156 else
157 {
158 cerr << "Socket audio mode: no socket_fd specified" << endl;
159 return -1;
160 }
161
162 if (al.present("socket_otype"))
163 otype = al.val("socket_otype"); // file type to send to client
164 else
165 otype = "riff";
166
167 inwave.save(tmpfile,otype);
168
169 // Because the client may receive many different types of file
170 // I send WV\n to it before the file itself
171 send(fd,"WV\n",3,0);
172 socket_send_file(fd,tmpfile);
173 unlink(tmpfile);
174
175 return 0;
176}
177
178static int play_aucomm_wave(EST_Wave &inwave, EST_Option &al)
179{
180 // Play wave by specified command
181 EST_String usrcommand, otype;
182 char tmpfile[2048];
183 char pref[2048];
184
185 if (al.present("-command"))
186 usrcommand = al.val("-command");
187 else if (getenv("NA_PLAY_COMMAND") != NULL)
188 usrcommand = getenv("NA_PLAY_COMMAND");
189 else
190 {
191 cerr << "Audio protocol set to COMMAND but no command specified\n";
192 return -1;
193 }
194
195 sprintf(tmpfile,"/tmp/audiofile_%05ld",(long)getpid());
196
197 if (al.present("-rate"))
198 inwave.resample(al.ival("-rate"));
199 if (al.present("-otype"))
200 otype = al.val("-otype");
201 else
202 otype = "raw";
203
204 if (inwave.save(tmpfile,otype) != write_ok)
205 {
206 cerr << "Audio writing file \"" << tmpfile << "\" in type \"" <<
207 otype << " failed " << endl;
208 return -1;
209 }
210
211 sprintf(pref,"FILE=%s;SR=%d;",tmpfile,inwave.sample_rate());
212
213 system((EST_String)pref+usrcommand.unquote('"'));
214
215 unlink(tmpfile); // so we don't fill up /tmp
216
217 return 0;
218}
219
220static int play_sunau_wave(EST_Wave &inwave, EST_Option &al)
221{
222 // Play wave through /dev/audio using 8K ulaw encoding
223 // works for Suns as well as Linux and FreeBSD machines
224 int rcode;
225 const char *audiodevice;
226
227 inwave.resample(8000);
228
229 if (al.present("-audiodevice"))
230 audiodevice = al.val("-audiodevice");
231 else
232 audiodevice = "/dev/audio";
233
234 // Should really do something cute about checking if /dev/audio
235 // is not in use
236 rcode = inwave.save(audiodevice,"ulaw");
237
238 return rcode;
239
240}
241
242EST_String options_supported_audio(void)
243{
244 // returns list of supported audio types
245 EST_String audios = "";
246
247 audios += "sunaudio"; // we always support this in spite of the hardware
248
249 audios += " audio_command";
250 if (nas_supported)
251 audios += " netaudio";
252 else if (esd_supported)
253 audios += " esdaudio";
254 if (sun16_supported)
255 audios += " sun16audio";
256 if (pulse_supported)
257 audios += " pulseaudio";
258 if (freebsd16_supported)
259 audios += " freebsd16audio";
260 if (linux16_supported)
261 audios += " linux16audio";
262 if (irix_supported)
263 audios += " irixaudio";
264 if (mplayer_supported)
265 audios += " mplayeraudio";
266 if (macosx_supported)
267 audios += "macosxaudio";
268 if (win32audio_supported)
269 audios += " win32audio";
270 if (os2audio_supported)
271 audios += " os2audio";
272
273 return audios;
274}
275
276int record_wave(EST_Wave &wave, EST_Option &al)
277{
278 // Record wave from audio device
279 char *sr;
280 EST_String protocol;
281
282 // For archaic reasons, if you are using NAS use DISPLAY or
283 // AUDIOSERVER
284 if ((sr = getenv("NA_PLAY_HOST")) != NULL)
285 if (!al.present("-display"))
286 al.add_item("-display", sr);
287
288 if (al.present("-p"))
289 protocol = al.val("-p");
290 else if ((sr=getenv("NA_PLAY_PROTOCOL")) != NULL)
291 protocol = sr;
292 else if (protocol == "")
293 {
294 if (pulse_supported)
295 protocol = "pulseaudio";
296 else if (nas_supported)
297 protocol = "netaudio"; // the default protocol
298 else if (esd_supported)
299 protocol = "esdaudio"; // the default protocol
300 else if (sun16_supported)
301 protocol = "sun16audio";
302 else if (freebsd16_supported)
303 protocol = "freebsd16audio";
304 else if (linux16_supported)
305 protocol = "linux16audio";
306 else if (irix_supported)
307 protocol = "irixaudio";
308 else if (win32audio_supported)
309 protocol = "win32audio";
310 else if (mplayer_supported)
311 protocol = "mplayeraudio";
312 else
313 protocol = "sunaudio";
314 }
315
316 if (upcase(protocol) == "NETAUDIO")
317 return record_nas_wave(wave,al);
318 else if (upcase(protocol) == "PULSEAUDIO")
319 return record_pulse_wave(wave,al);
320 else if (upcase(protocol) == "ESDAUDIO")
321 return record_esd_wave(wave,al);
322 else if (upcase(protocol) == "SUN16AUDIO")
323 return record_sun16_wave(wave,al);
324 else if ((upcase(protocol) == "FREEBSD16AUDIO") ||
325 (upcase(protocol) == "LINUX16AUDIO"))
326 return record_linux_wave(wave,al);
327 else if (upcase(protocol) == "SUNAUDIO")
328 return record_sunau_wave(wave,al);
329 else
330 {
331 cerr << "NA_RECORD: \"" << protocol <<
332 "\" EST current has no record support" << endl;
333 return -1;
334 }
335}
336
337static int record_sunau_wave(EST_Wave &wave, EST_Option &al)
338{
339 int num_samples,i,r,n;
340 int audio;
341 unsigned char *ulawwave;
342 short *waveform;
343 const int AUDIOBUFFSIZE = 256;
344 const char *audiodevice;
345
346 if (al.present("-audiodevice"))
347 audiodevice = al.val("-audiodevice");
348 else
349 audiodevice = "/dev/audio";
350
351 if ((audio = open(audiodevice, O_RDONLY)) == -1)
352 {
353 cerr << "SUN16: can't open " << audiodevice << " for reading" << endl;
354 return -1;
355 }
356
357 num_samples = (int)(8000*al.fval("-time"));
358 ulawwave = walloc(unsigned char,num_samples);
359
360 for (r=i=0; i < num_samples; i+= r)
361 {
362 if (num_samples > i+AUDIOBUFFSIZE)
363 n = AUDIOBUFFSIZE;
364 else
365 n = num_samples-i;
366 r = read(audio,&ulawwave[i], n);
367 if (r <= 0)
368 {
369 cerr << "sunaudio: failed to read from audio device" << endl;
370 close(audio);
371 wfree(ulawwave);
372 return -1;
373 }
374 }
375
376 wave.resize(num_samples);
377 wave.set_sample_rate(8000);
378 waveform = wave.values().memory();
379
380 ulaw_to_short(ulawwave,waveform,num_samples);
381 wave.resample(al.ival("-sample_rate"));
382
383 close(audio);
384 wfree(ulawwave);
385 return 0;
386}
387
float fval(const EST_String &rkey, int m=1) const
Definition EST_Option.cc:98
int ival(const EST_String &rkey, int m=1) const
Definition EST_Option.cc:76
EST_String unquote(const char quotec) const
Remove quotes and unprotect internal quotes.
int add_item(const K &rkey, const V &rval, int no_search=0)
add key-val pair to list
Definition EST_TKVL.cc:248
const V & val(const K &rkey, bool m=0) const
return value according to key (const)
Definition EST_TKVL.cc:145
const int present(const K &rkey) const
Returns true if key is present.
Definition EST_TKVL.cc:222
const T * memory() const
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
void resample(int rate)
Resample waveform to rate
Definition EST_Wave.cc:489
void resize(int num_samples, int num_channels=EST_ALL, int set=1)
resize the waveform
Definition EST_Wave.h:184
void set_sample_rate(const int n)
Set sampling rate to n
Definition EST_Wave.h:149