Edinburgh Speech Tools 2.4-release
 
Loading...
Searching...
No Matches
sun16audio.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 : Alan W Black */
34/* Date : July 1997 */
35/*-----------------------------------------------------------------------*/
36/* Optional Sun 16bit linear support for /dev/audio */
37/* This only works when compiled under Solaris or SunOS as it requires */
38/* Sun's headers, and much more importantly Sun's /dev/audio. This */
39/* of course will access the *local* machine's /dev/audio definite not */
40/* the "network is the computer" maxim but sometimes you might want */
41/* this */
42/* */
43/*=======================================================================*/
44
45#include <cstdio>
46#include <cstring>
47#include <cstdlib>
48#include <cctype>
49#include <sys/stat.h>
50#include <sys/types.h>
51#include <fcntl.h>
52#include "EST_cutils.h"
53#include "EST_Wave.h"
54#include "EST_Option.h"
55#include "audioP.h"
56#include "EST_io_aux.h"
57#include "EST_unix.h"
58
59#ifdef SUPPORT_SUN16
60#include <sys/filio.h>
61#if defined(__svr4__) || defined(SYSV) || defined(SVR4)
62/* Solaris */
63#include <sys/audioio.h>
64#else
65/* Sunos */
66#include <sun/audioio.h>
67#endif
68
69static int sun16_check_device(int audio);
70static int sun16_set_info(int audio, int sample_rate);
71
72int sun16_supported = TRUE;
73
74/* supported sampling frequencies for Sun dbri device */
75static int dev_sr[] = {8000, 9600, 11025, 16000, 18900, 22050, 32000,
76 37800, 44100, 48000, -1};
77
78#define AUDIOBUFFSIZE 256
79
80int play_sun16_wave(EST_Wave &inwave, EST_Option &al)
81{
82 int sample_rate;
83 short *waveform;
84 FILE *fdaudio;
85 int num_samples;
86 int audio;
87 int i,r,n;
88 char *audiodevice;
89
90 sample_rate = inwave.sample_rate();
91 int samp_rate_ok = FALSE;
92 for (i=0; dev_sr[i] != -1; i++)
93 if (sample_rate == dev_sr[i])
94 samp_rate_ok = TRUE;
95 if (samp_rate_ok == FALSE)
96 {
97 if (sample_rate == 10000)
98 inwave.resample(9600); // just sounds much better than 16000
99 else
100 inwave.resample(16000);
101 }
102
103 if (al.present("-audiodevice"))
104 audiodevice = al.val("-audiodevice");
105 else if ((audiodevice = getenv("AUDIODEV")) == NULL)
106 audiodevice = "/dev/audio";
107
108 if ((fdaudio = fopen(audiodevice,"wb")) == NULL)
109 {
110 cerr << "SUN16: can't open " << audiodevice << endl;
111 return -1;
112 }
113 // As I can't find open in an Sun CC include file I'll avoid it
114 audio = fileno(fdaudio);
115
116 waveform = inwave.values().memory();
117 num_samples = inwave.num_samples();
118 sample_rate = inwave.sample_rate();
119
120 if (sun16_check_device(audio) == FALSE)
121 {
122 cerr << "SUN16: device doesn't support 16bit linear." << endl;
123 fclose(fdaudio);
124 return -1;
125 }
126
127 if (sun16_set_info(audio,sample_rate) == FALSE)
128 {
129 cerr << "SUN16: unable to set sample rate " <<
130 sample_rate << endl;
131 fclose(fdaudio);
132 return -1;
133 }
134
135 for (i=0; i < num_samples; i += r/2)
136 {
137 if (num_samples > i+AUDIOBUFFSIZE)
138 n = AUDIOBUFFSIZE;
139 else
140 n = num_samples-i;
141 r = write(audio,&waveform[i], n*2);
142 if (r == 0)
143 {
144 cerr << "SUN16: failed to write to buffer" <<
145 sample_rate << endl;
146 fclose(fdaudio);
147 return -1;
148 }
149 // needed to prevent foul ups under Java.
150// ioctl(audio, AUDIO_DRAIN, 0);
151 }
152
153 fclose(fdaudio);
154 return 1;
155}
156
157static int sun16_check_device(int audio)
158{
159#ifdef __svr4__
160/* Solaris */
161 audio_device_t type;
162
163 ioctl(audio, AUDIO_DRAIN, 0); /* drain everything out */
164
165 if ((ioctl(audio, AUDIO_GETDEV, &type) != -1) &&
166 ((streq("SUNW,CS4231",type.name)) || /* Newer Suns (ultras) */
167 (streq("SUNW,dbri",type.name)) || /* Older Suns (SS10s SS20s) */
168 (streq("SUNW,audiots",type.name)) || /* For stations more advanced than ultras */
169 (streq("SUNW,sb16",type.name)))) /* i386 machines */
170 return TRUE;
171 else
172 return FALSE;
173#else
174/* SunOS */
175 int type;
176
177 ioctl(audio, AUDIO_DRAIN, 0); /* drain everything out */
178
179 if ((ioctl(audio, AUDIO_GETDEV, &type) != -1) &&
180 ((type == AUDIO_DEV_SPEAKERBOX) || (type == AUDIO_DEV_CODEC)))
181 return TRUE;
182 else
183 return FALSE;
184#endif
185
186}
187
188static int sun16_set_info(int audio, int sample_rate)
189{
190 audio_info_t info;
191
192 ioctl(audio, AUDIO_GETINFO, &info);
193
194 info.play.sample_rate = sample_rate;
195 info.play.encoding = AUDIO_ENCODING_LINEAR;
196 info.play.precision = 16;
197 info.play.channels = 1;
198
199 if (ioctl(audio, AUDIO_SETINFO, &info) == -1)
200 return FALSE;
201 else
202 return TRUE;
203}
204
205static int sun16_setrecord_info(int audio, int sample_rate)
206{
207 /* As the device is always recording, changing sample rate/encoding */
208 /* can mess up the stream, so stop recording, flush the buffer and */
209 /* then set the formats and restart recording */
210 audio_info_t info;
211 int read_size,i,r;
212 unsigned char buff[64];
213
214 ioctl(audio, AUDIO_GETINFO, &info);
215
216 info.record.pause = 1;
217
218 ioctl(audio, AUDIO_SETINFO, &info);
219
220 /* Read any existing recorded stuff in the buffer */
221 ioctl(audio, FIONREAD, &read_size);
222 for (r=i=0; (i < read_size); i += r)
223 r = read(audio,buff,64);
224
225 /* Now set up the recording format */
226 ioctl(audio, AUDIO_GETINFO, &info);
227 info.record.sample_rate = sample_rate;
228 info.record.encoding = AUDIO_ENCODING_LINEAR;
229 info.record.precision = 16;
230 info.record.channels = 1;
231 info.record.pause = 0;
232 info.record.samples = 0;
233 info.record.error = 0;
234
235 if (ioctl(audio, AUDIO_SETINFO, &info) == -1)
236 return FALSE;
237 else
238 return TRUE;
239}
240
241int record_sun16_wave(EST_Wave &wave, EST_Option &al)
242{
243 int desired_sample_rate = 16000;
244 int actual_sample_rate;
245 short *waveform;
246 int audio=-1;
247 int num_samples;
248 int i,r,n;
249
250 desired_sample_rate = al.ival("-sample_rate");
251 actual_sample_rate = -1;
252 for (i=0; dev_sr[i] != -1; i++)
253 if (desired_sample_rate == dev_sr[i])
254 actual_sample_rate = desired_sample_rate;
255 if (actual_sample_rate == -1)
256 actual_sample_rate = 16000;
257
258 if ((audio = open("/dev/audio",O_RDONLY)) == -1)
259 {
260 cerr << "SUN16: can't open /dev/audio for reading" << endl;
261 return -1;
262 }
263
264 if (sun16_check_device(audio) == FALSE)
265 {
266 cerr << "SUN16: device doesn't support 16bit linear." << endl;
267 close(audio);
268 return -1;
269 }
270
271 if (sun16_setrecord_info(audio,actual_sample_rate) == FALSE)
272 {
273 cerr << "SUN16: unable to set sample rate " <<
274 actual_sample_rate << endl;
275 close(audio);
276 return -1;
277 }
278
279 wave.resize((int)(actual_sample_rate*al.fval("-time")));
280 wave.set_sample_rate(actual_sample_rate);
281 num_samples = wave.num_samples();
282 waveform = wave.values().memory();
283
284 int read_size;
285
286 for (r=i=0; i < num_samples; i+= r)
287 {
288 if (num_samples > i+AUDIOBUFFSIZE)
289 n = AUDIOBUFFSIZE;
290 else
291 n = num_samples-i;
292 ioctl(audio, FIONREAD, &read_size);
293 if (read_size == 0)
294 {
295 r = 0;
296 continue; // nothing to read yet
297 }
298 if (n > read_size/2)
299 n = read_size/2;
300 r = read(audio,&waveform[i], n*2);
301 r /= 2;
302 if (r <= 0)
303 {
304 cerr << "SUN16: failed to read from audio device" << endl;
305 close(audio);
306 return -1;
307 }
308
309 }
310
311 close(audio);
312 if (actual_sample_rate != desired_sample_rate)
313 wave.resample(desired_sample_rate);
314 return 0;
315}
316
317#else
318int sun16_supported = FALSE;
319
320int play_sun16_wave(EST_Wave &inwave, EST_Option &al)
321{
322 (void)inwave;
323 (void)al;
324 cerr << "Sun 16bit linear not supported" << endl;
325 return -1;
326}
327
328int record_sun16_wave(EST_Wave &inwave, EST_Option &al)
329{
330 (void)inwave;
331 (void)al;
332 cerr << "Sun 16bit linear not supported" << endl;
333 return -1;
334}
335
336#endif
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
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 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
int num_samples() const
return the number of samples in the waveform
Definition EST_Wave.h:143
void set_sample_rate(const int n)
Set sampling rate to n
Definition EST_Wave.h:149