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