1 /* libSoX direct to Sun Audio Driver
3 * Added by Chris Bagwell (cbagwell@sprynet.com) on 2/26/96
4 * Based on oss handler.
6 * Cleaned up changes of format somewhat in sunstartwrite on 03/31/98
11 * Copyright 1997 Chris Bagwell And Sundry Contributors
12 * This source code is freely redistributable and may be used for
13 * any purpose. This copyright notice must be maintained.
14 * Rick Richardson, Lance Norskog And Sundry Contributors are not
15 * responsible for the consequences of using this software.
20 #include <sys/ioctl.h>
21 #include <sys/types.h>
22 #ifdef HAVE_SUN_AUDIOIO_H
23 #include <sun/audioio.h>
25 #include <sys/audioio.h>
28 #if !defined(__NetBSD__) && !defined(__OpenBSD__)
35 typedef sox_fileinfo_t priv_t
;
37 * Do anything required before you start reading samples.
39 * Find out sampling rate,
40 * size and encoding of samples,
43 static int sox_sunstartread(sox_format_t
* ft
)
45 priv_t
*file
= (priv_t
*)ft
->priv
;
46 size_t samplesize
, encoding
;
47 audio_info_t audio_if
;
49 audio_device_t audio_dev
;
53 lsx_set_signal_defaults(ft
);
55 /* Hard-code for now. */
59 file
->buf
= lsx_malloc (file
->size
);
61 if (ft
->encoding
.encoding
== SOX_ENCODING_UNKNOWN
) ft
->encoding
.encoding
= SOX_ENCODING_ULAW
;
64 /* Read in old values, change to what we need and then send back */
65 if (ioctl(fileno(ft
->fp
), AUDIO_GETDEV
, &audio_dev
) < 0) {
66 lsx_fail_errno(ft
,errno
,"Unable to get device information.");
69 lsx_report("Hardware detected: %s",audio_dev
.name
);
70 if (strcmp("SUNW,am79c30",audio_dev
.name
) == 0)
76 /* If simple hardware detected in force data to ulaw. */
79 if (ft
->encoding
.bits_per_sample
== 8)
81 if (ft
->encoding
.encoding
!= SOX_ENCODING_ULAW
&&
82 ft
->encoding
.encoding
!= SOX_ENCODING_ALAW
)
84 lsx_report("Warning: Detected simple hardware. Forcing output to ULAW");
85 ft
->encoding
.encoding
= SOX_ENCODING_ULAW
;
88 else if (ft
->encoding
.bits_per_sample
== 16)
90 lsx_report("Warning: Detected simple hardware. Forcing output to ULAW");
91 ft
->encoding
.bits_per_sample
= 8;
92 ft
->encoding
.encoding
= SOX_ENCODING_ULAW
;
96 if (ft
->encoding
.bits_per_sample
== 8) {
98 if (ft
->encoding
.encoding
!= SOX_ENCODING_ULAW
&&
99 ft
->encoding
.encoding
!= SOX_ENCODING_ALAW
&&
100 ft
->encoding
.encoding
!= SOX_ENCODING_SIGN2
) {
101 lsx_fail_errno(ft
,SOX_EFMT
,"Sun audio driver only supports ULAW, ALAW, and signed linear for bytes.");
104 if ((ft
->encoding
.encoding
== SOX_ENCODING_ULAW
||
105 ft
->encoding
.encoding
== SOX_ENCODING_ALAW
) &&
106 ft
->signal
.channels
== 2)
108 lsx_report("Warning: only support mono for ULAW and ALAW data. Forcing to mono.");
109 ft
->signal
.channels
= 1;
112 else if (ft
->encoding
.bits_per_sample
== 16) {
114 if (ft
->encoding
.encoding
!= SOX_ENCODING_SIGN2
) {
115 lsx_fail_errno(ft
,SOX_EFMT
,"Sun audio driver only supports signed linear for words.");
120 lsx_fail_errno(ft
,SOX_EFMT
,"Sun audio driver only supports bytes and words");
124 if (ft
->signal
.channels
== 0) ft
->signal
.channels
= 1;
125 else if (ft
->signal
.channels
> 1) {
126 lsx_report("Warning: some Sun audio devices can not play stereo");
127 lsx_report("at all or sometimes only with signed words. If the");
128 lsx_report("sound seems sluggish then this is probably the case.");
129 lsx_report("Try forcing output to signed words or use the avg");
130 lsx_report("filter to reduce the number of channels.");
131 ft
->signal
.channels
= 2;
134 /* Read in old values, change to what we need and then send back */
135 if (ioctl(fileno(ft
->fp
), AUDIO_GETINFO
, &audio_if
) < 0) {
136 lsx_fail_errno(ft
,errno
,"Unable to initialize /dev/audio");
139 audio_if
.record
.precision
= samplesize
;
140 audio_if
.record
.channels
= ft
->signal
.channels
;
141 audio_if
.record
.sample_rate
= ft
->signal
.rate
;
142 if (ft
->encoding
.encoding
== SOX_ENCODING_ULAW
)
143 encoding
= AUDIO_ENCODING_ULAW
;
144 else if (ft
->encoding
.encoding
== SOX_ENCODING_ALAW
)
145 encoding
= AUDIO_ENCODING_ALAW
;
147 encoding
= AUDIO_ENCODING_LINEAR
;
148 audio_if
.record
.encoding
= encoding
;
150 ioctl(fileno(ft
->fp
), AUDIO_SETINFO
, &audio_if
);
151 if (audio_if
.record
.precision
!= samplesize
) {
152 lsx_fail_errno(ft
,errno
,"Unable to initialize sample size for /dev/audio");
155 if (audio_if
.record
.channels
!= ft
->signal
.channels
) {
156 lsx_fail_errno(ft
,errno
,"Unable to initialize number of channels for /dev/audio");
159 if (audio_if
.record
.sample_rate
!= ft
->signal
.rate
) {
160 lsx_fail_errno(ft
,errno
,"Unable to initialize rate for /dev/audio");
163 if (audio_if
.record
.encoding
!= encoding
) {
164 lsx_fail_errno(ft
,errno
,"Unable to initialize encoding for /dev/audio");
167 /* Flush any data in the buffers - its probably in the wrong format */
168 #if defined(__NetBSD__) || defined(__OpenBSD__)
169 ioctl(fileno(ft
->fp
), AUDIO_FLUSH
);
170 #elif defined __GLIBC__
171 ioctl(fileno(ft
->fp
), (unsigned long int)I_FLUSH
, FLUSHR
);
173 ioctl(fileno(ft
->fp
), I_FLUSH
, FLUSHR
);
175 /* Change to non-buffered I/O*/
176 setvbuf(ft
->fp
, NULL
, _IONBF
, sizeof(char) * file
->size
);
178 return (SOX_SUCCESS
);
181 static int sox_sunstartwrite(sox_format_t
* ft
)
183 priv_t
*file
= (priv_t
*)ft
->priv
;
184 size_t samplesize
, encoding
;
185 audio_info_t audio_if
;
187 audio_device_t audio_dev
;
191 /* Hard-code for now. */
195 file
->buf
= lsx_malloc (file
->size
);
198 /* Read in old values, change to what we need and then send back */
199 if (ioctl(fileno(ft
->fp
), AUDIO_GETDEV
, &audio_dev
) < 0) {
200 lsx_fail_errno(ft
,errno
,"Unable to get device information.");
203 lsx_report("Hardware detected: %s",audio_dev
.name
);
204 if (strcmp("SUNW,am79c30",audio_dev
.name
) == 0)
212 if (ft
->encoding
.bits_per_sample
== 8)
214 if (ft
->encoding
.encoding
!= SOX_ENCODING_ULAW
&&
215 ft
->encoding
.encoding
!= SOX_ENCODING_ALAW
)
217 lsx_report("Warning: Detected simple hardware. Forcing output to ULAW");
218 ft
->encoding
.encoding
= SOX_ENCODING_ULAW
;
221 else if (ft
->encoding
.bits_per_sample
== 16)
223 lsx_report("Warning: Detected simple hardware. Forcing output to ULAW");
224 ft
->encoding
.bits_per_sample
= 8;
225 ft
->encoding
.encoding
= SOX_ENCODING_ULAW
;
229 if (ft
->encoding
.bits_per_sample
== 8)
232 if (ft
->encoding
.encoding
== SOX_ENCODING_UNKNOWN
)
233 ft
->encoding
.encoding
= SOX_ENCODING_ULAW
;
234 else if (ft
->encoding
.encoding
!= SOX_ENCODING_ULAW
&&
235 ft
->encoding
.encoding
!= SOX_ENCODING_ALAW
&&
236 ft
->encoding
.encoding
!= SOX_ENCODING_SIGN2
) {
237 lsx_report("Sun Audio driver only supports ULAW, ALAW, and Signed Linear for bytes.");
238 lsx_report("Forcing to ULAW");
239 ft
->encoding
.encoding
= SOX_ENCODING_ULAW
;
241 if ((ft
->encoding
.encoding
== SOX_ENCODING_ULAW
||
242 ft
->encoding
.encoding
== SOX_ENCODING_ALAW
) &&
243 ft
->signal
.channels
== 2)
245 lsx_report("Warning: only support mono for ULAW and ALAW data. Forcing to mono.");
246 ft
->signal
.channels
= 1;
250 else if (ft
->encoding
.bits_per_sample
== 16) {
252 if (ft
->encoding
.encoding
== SOX_ENCODING_UNKNOWN
)
253 ft
->encoding
.encoding
= SOX_ENCODING_SIGN2
;
254 else if (ft
->encoding
.encoding
!= SOX_ENCODING_SIGN2
) {
255 lsx_report("Sun Audio driver only supports Signed Linear for words.");
256 lsx_report("Forcing to Signed Linear");
257 ft
->encoding
.encoding
= SOX_ENCODING_SIGN2
;
261 lsx_report("Sun Audio driver only supports bytes and words");
262 ft
->encoding
.bits_per_sample
= 16;
263 ft
->encoding
.encoding
= SOX_ENCODING_SIGN2
;
267 if (ft
->signal
.channels
> 1) ft
->signal
.channels
= 2;
269 /* Read in old values, change to what we need and then send back */
270 if (ioctl(fileno(ft
->fp
), AUDIO_GETINFO
, &audio_if
) < 0) {
271 lsx_fail_errno(ft
,errno
,"Unable to initialize /dev/audio");
274 audio_if
.play
.precision
= samplesize
;
275 audio_if
.play
.channels
= ft
->signal
.channels
;
276 audio_if
.play
.sample_rate
= ft
->signal
.rate
;
277 if (ft
->encoding
.encoding
== SOX_ENCODING_ULAW
)
278 encoding
= AUDIO_ENCODING_ULAW
;
279 else if (ft
->encoding
.encoding
== SOX_ENCODING_ALAW
)
280 encoding
= AUDIO_ENCODING_ALAW
;
282 encoding
= AUDIO_ENCODING_LINEAR
;
283 audio_if
.play
.encoding
= encoding
;
285 ioctl(fileno(ft
->fp
), AUDIO_SETINFO
, &audio_if
);
286 if (audio_if
.play
.precision
!= samplesize
) {
287 lsx_fail_errno(ft
,errno
,"Unable to initialize sample size for /dev/audio");
290 if (audio_if
.play
.channels
!= ft
->signal
.channels
) {
291 lsx_fail_errno(ft
,errno
,"Unable to initialize number of channels for /dev/audio");
294 if (audio_if
.play
.sample_rate
!= ft
->signal
.rate
) {
295 lsx_fail_errno(ft
,errno
,"Unable to initialize rate for /dev/audio");
298 if (audio_if
.play
.encoding
!= encoding
) {
299 lsx_fail_errno(ft
,errno
,"Unable to initialize encoding for /dev/audio");
302 /* Change to non-buffered I/O */
303 setvbuf(ft
->fp
, NULL
, _IONBF
, sizeof(char) * file
->size
);
305 return (SOX_SUCCESS
);
308 LSX_FORMAT_HANDLER(sunau
)
310 static char const * const names
[] = {"sunau", NULL
};
311 static unsigned const write_encodings
[] = {
312 SOX_ENCODING_ULAW
, 8, 0,
313 SOX_ENCODING_ALAW
, 8, 0,
314 SOX_ENCODING_SIGN2
, 8, 16, 0,
316 static sox_format_handler_t
const handler
= {SOX_LIB_VERSION_CODE
,
317 "Sun audio device driver", names
, SOX_FILE_DEVICE
,
318 sox_sunstartread
, lsx_rawread
, lsx_rawstopread
,
319 sox_sunstartwrite
, lsx_rawwrite
, lsx_rawstopwrite
,
320 NULL
, write_encodings
, NULL
, sizeof(priv_t
)