sun.c revision 1.7.8.1 1 1.7.8.1 tls /* $NetBSD: sun.c,v 1.7.8.1 2014/08/20 00:04:56 tls Exp $ */
2 1.1 mrg
3 1.1 mrg /*
4 1.1 mrg * Copyright (c) 2002 Matthew R. Green
5 1.1 mrg * All rights reserved.
6 1.1 mrg *
7 1.1 mrg * Redistribution and use in source and binary forms, with or without
8 1.1 mrg * modification, are permitted provided that the following conditions
9 1.1 mrg * are met:
10 1.1 mrg * 1. Redistributions of source code must retain the above copyright
11 1.1 mrg * notice, this list of conditions and the following disclaimer.
12 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 mrg * notice, this list of conditions and the following disclaimer in the
14 1.1 mrg * documentation and/or other materials provided with the distribution.
15 1.1 mrg *
16 1.1 mrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.1 mrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.1 mrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.1 mrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.1 mrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 1.1 mrg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 1.1 mrg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 1.1 mrg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 1.1 mrg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.1 mrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.1 mrg * SUCH DAMAGE.
27 1.1 mrg */
28 1.1 mrg
29 1.1 mrg /*
30 1.1 mrg * XXX this is slightly icky in places...
31 1.1 mrg */
32 1.3 agc #include <sys/cdefs.h>
33 1.3 agc
34 1.3 agc #ifndef lint
35 1.7.8.1 tls __RCSID("$NetBSD: sun.c,v 1.7.8.1 2014/08/20 00:04:56 tls Exp $");
36 1.3 agc #endif
37 1.3 agc
38 1.1 mrg
39 1.1 mrg #include <sys/types.h>
40 1.1 mrg #include <sys/audioio.h>
41 1.1 mrg #include <sys/ioctl.h>
42 1.1 mrg #include <sys/time.h>
43 1.1 mrg
44 1.1 mrg #include <ctype.h>
45 1.1 mrg #include <err.h>
46 1.1 mrg #include <stdio.h>
47 1.1 mrg #include <stdlib.h>
48 1.1 mrg #include <string.h>
49 1.7.8.1 tls #include <unistd.h>
50 1.1 mrg
51 1.1 mrg #include "libaudio.h"
52 1.7.8.1 tls #include "auconv.h"
53 1.1 mrg
54 1.1 mrg /*
55 1.1 mrg * SunOS/NeXT .au format helpers
56 1.1 mrg */
57 1.7 joerg static const struct {
58 1.1 mrg int file_encoding;
59 1.1 mrg int encoding;
60 1.1 mrg int precision;
61 1.1 mrg } file2sw_encodings[] = {
62 1.1 mrg { AUDIO_FILE_ENCODING_MULAW_8, AUDIO_ENCODING_ULAW, 8 },
63 1.2 mrg { AUDIO_FILE_ENCODING_LINEAR_8, AUDIO_ENCODING_SLINEAR_BE, 8 },
64 1.2 mrg { AUDIO_FILE_ENCODING_LINEAR_16, AUDIO_ENCODING_SLINEAR_BE, 16 },
65 1.2 mrg { AUDIO_FILE_ENCODING_LINEAR_24, AUDIO_ENCODING_SLINEAR_BE, 24 },
66 1.2 mrg { AUDIO_FILE_ENCODING_LINEAR_32, AUDIO_ENCODING_SLINEAR_BE, 32 },
67 1.1 mrg #if 0
68 1.1 mrg /*
69 1.1 mrg * we should make some of these available. the, eg ultrasparc, port
70 1.1 mrg * can use the VIS instructions (if available) do do some of these
71 1.1 mrg * mpeg ones.
72 1.1 mrg */
73 1.1 mrg { AUDIO_FILE_ENCODING_FLOAT, AUDIO_ENCODING_ULAW, 32 },
74 1.1 mrg { AUDIO_FILE_ENCODING_DOUBLE, AUDIO_ENCODING_ULAW, 64 },
75 1.1 mrg { AUDIO_FILE_ENCODING_ADPCM_G721, AUDIO_ENCODING_ULAW, 4 },
76 1.1 mrg { AUDIO_FILE_ENCODING_ADPCM_G722, AUDIO_ENCODING_ULAW, 0 },
77 1.1 mrg { AUDIO_FILE_ENCODING_ADPCM_G723_3, AUDIO_ENCODING_ULAW, 3 },
78 1.1 mrg { AUDIO_FILE_ENCODING_ADPCM_G723_5, AUDIO_ENCODING_ULAW, 5 },
79 1.1 mrg #endif
80 1.1 mrg { AUDIO_FILE_ENCODING_ALAW_8, AUDIO_ENCODING_ALAW, 8 },
81 1.5 christos { -1, -1, -1 }
82 1.1 mrg };
83 1.1 mrg
84 1.1 mrg int
85 1.7 joerg audio_sun_to_encoding(int sun_encoding, u_int *encp, u_int *precp)
86 1.1 mrg {
87 1.1 mrg int i;
88 1.1 mrg
89 1.1 mrg for (i = 0; file2sw_encodings[i].file_encoding != -1; i++)
90 1.1 mrg if (file2sw_encodings[i].file_encoding == sun_encoding) {
91 1.1 mrg *precp = file2sw_encodings[i].precision;
92 1.1 mrg *encp = file2sw_encodings[i].encoding;
93 1.1 mrg return (0);
94 1.1 mrg }
95 1.1 mrg return (1);
96 1.1 mrg }
97 1.1 mrg
98 1.1 mrg int
99 1.7 joerg audio_encoding_to_sun(int encoding, int precision, int *sunep)
100 1.1 mrg {
101 1.1 mrg int i;
102 1.1 mrg
103 1.1 mrg for (i = 0; file2sw_encodings[i].file_encoding != -1; i++)
104 1.1 mrg if (file2sw_encodings[i].encoding == encoding &&
105 1.1 mrg file2sw_encodings[i].precision == precision) {
106 1.1 mrg *sunep = file2sw_encodings[i].file_encoding;
107 1.1 mrg return (0);
108 1.1 mrg }
109 1.1 mrg return (1);
110 1.1 mrg }
111 1.7.8.1 tls
112 1.7.8.1 tls int
113 1.7.8.1 tls sun_prepare_header(struct write_info *wi, void **hdrp, size_t *lenp, int *leftp)
114 1.7.8.1 tls {
115 1.7.8.1 tls static int warned = 0;
116 1.7.8.1 tls static sun_audioheader auh;
117 1.7.8.1 tls int sunenc, oencoding = wi->encoding;
118 1.7.8.1 tls
119 1.7.8.1 tls /* only perform conversions if we don't specify the encoding */
120 1.7.8.1 tls switch (wi->encoding) {
121 1.7.8.1 tls
122 1.7.8.1 tls case AUDIO_ENCODING_ULINEAR_LE:
123 1.7.8.1 tls #if BYTE_ORDER == LITTLE_ENDIAN
124 1.7.8.1 tls case AUDIO_ENCODING_ULINEAR:
125 1.7.8.1 tls #endif
126 1.7.8.1 tls if (wi->precision == 16 || wi->precision == 32)
127 1.7.8.1 tls wi->encoding = AUDIO_ENCODING_SLINEAR_BE;
128 1.7.8.1 tls break;
129 1.7.8.1 tls
130 1.7.8.1 tls case AUDIO_ENCODING_ULINEAR_BE:
131 1.7.8.1 tls #if BYTE_ORDER == BIG_ENDIAN
132 1.7.8.1 tls case AUDIO_ENCODING_ULINEAR:
133 1.7.8.1 tls #endif
134 1.7.8.1 tls if (wi->precision == 16 || wi->precision == 32)
135 1.7.8.1 tls wi->encoding = AUDIO_ENCODING_SLINEAR_BE;
136 1.7.8.1 tls break;
137 1.7.8.1 tls
138 1.7.8.1 tls case AUDIO_ENCODING_SLINEAR_LE:
139 1.7.8.1 tls #if BYTE_ORDER == LITTLE_ENDIAN
140 1.7.8.1 tls case AUDIO_ENCODING_SLINEAR:
141 1.7.8.1 tls #endif
142 1.7.8.1 tls if (wi->precision == 16 || wi->precision == 32)
143 1.7.8.1 tls wi->encoding = AUDIO_ENCODING_SLINEAR_BE;
144 1.7.8.1 tls break;
145 1.7.8.1 tls
146 1.7.8.1 tls #if BYTE_ORDER == BIG_ENDIAN
147 1.7.8.1 tls case AUDIO_ENCODING_SLINEAR:
148 1.7.8.1 tls wi->encoding = AUDIO_ENCODING_SLINEAR_BE;
149 1.7.8.1 tls break;
150 1.7.8.1 tls #endif
151 1.7.8.1 tls }
152 1.7.8.1 tls
153 1.7.8.1 tls /* if we can't express this as a Sun header, don't write any */
154 1.7.8.1 tls if (audio_encoding_to_sun(wi->encoding, wi->precision, &sunenc) != 0) {
155 1.7.8.1 tls if (!wi->qflag && !warned) {
156 1.7.8.1 tls const char *s = audio_enc_from_val(oencoding);
157 1.7.8.1 tls
158 1.7.8.1 tls if (s == NULL)
159 1.7.8.1 tls s = "(unknown)";
160 1.7.8.1 tls warnx("failed to convert to sun encoding from %s "
161 1.7.8.1 tls "(precision %d);\nSun audio header not written",
162 1.7.8.1 tls s, wi->precision);
163 1.7.8.1 tls }
164 1.7.8.1 tls wi->format = AUDIO_FORMAT_NONE;
165 1.7.8.1 tls warned = 1;
166 1.7.8.1 tls return -1;
167 1.7.8.1 tls }
168 1.7.8.1 tls
169 1.7.8.1 tls auh.magic = htonl(AUDIO_FILE_MAGIC);
170 1.7.8.1 tls if (wi->outfd == STDOUT_FILENO)
171 1.7.8.1 tls auh.data_size = htonl(AUDIO_UNKNOWN_SIZE);
172 1.7.8.1 tls else if (wi->total_size != -1)
173 1.7.8.1 tls auh.data_size = htonl(wi->total_size);
174 1.7.8.1 tls else
175 1.7.8.1 tls auh.data_size = 0;
176 1.7.8.1 tls auh.encoding = htonl(sunenc);
177 1.7.8.1 tls auh.sample_rate = htonl(wi->sample_rate);
178 1.7.8.1 tls auh.channels = htonl(wi->channels);
179 1.7.8.1 tls if (wi->header_info) {
180 1.7.8.1 tls int len, infolen;
181 1.7.8.1 tls
182 1.7.8.1 tls infolen = ((len = strlen(wi->header_info)) + 7) & 0xfffffff8;
183 1.7.8.1 tls *leftp = infolen - len;
184 1.7.8.1 tls auh.hdr_size = htonl(sizeof(auh) + infolen);
185 1.7.8.1 tls } else {
186 1.7.8.1 tls *leftp = sizeof(audio_default_info);
187 1.7.8.1 tls auh.hdr_size = htonl(sizeof(auh) + *leftp);
188 1.7.8.1 tls }
189 1.7.8.1 tls *(sun_audioheader **)hdrp = &auh;
190 1.7.8.1 tls *lenp = sizeof auh;
191 1.7.8.1 tls return 0;
192 1.7.8.1 tls }
193 1.7.8.1 tls
194 1.7.8.1 tls write_conv_func
195 1.7.8.1 tls sun_write_get_conv_func(struct write_info *wi)
196 1.7.8.1 tls {
197 1.7.8.1 tls write_conv_func conv_func = NULL;
198 1.7.8.1 tls
199 1.7.8.1 tls /* only perform conversions if we don't specify the encoding */
200 1.7.8.1 tls switch (wi->encoding) {
201 1.7.8.1 tls
202 1.7.8.1 tls case AUDIO_ENCODING_ULINEAR_LE:
203 1.7.8.1 tls #if BYTE_ORDER == LITTLE_ENDIAN
204 1.7.8.1 tls case AUDIO_ENCODING_ULINEAR:
205 1.7.8.1 tls #endif
206 1.7.8.1 tls if (wi->precision == 16)
207 1.7.8.1 tls conv_func = change_sign16_swap_bytes_le;
208 1.7.8.1 tls else if (wi->precision == 32)
209 1.7.8.1 tls conv_func = change_sign32_swap_bytes_le;
210 1.7.8.1 tls break;
211 1.7.8.1 tls
212 1.7.8.1 tls case AUDIO_ENCODING_ULINEAR_BE:
213 1.7.8.1 tls #if BYTE_ORDER == BIG_ENDIAN
214 1.7.8.1 tls case AUDIO_ENCODING_ULINEAR:
215 1.7.8.1 tls #endif
216 1.7.8.1 tls if (wi->precision == 16)
217 1.7.8.1 tls conv_func = change_sign16_be;
218 1.7.8.1 tls else if (wi->precision == 32)
219 1.7.8.1 tls conv_func = change_sign32_be;
220 1.7.8.1 tls break;
221 1.7.8.1 tls
222 1.7.8.1 tls case AUDIO_ENCODING_SLINEAR_LE:
223 1.7.8.1 tls #if BYTE_ORDER == LITTLE_ENDIAN
224 1.7.8.1 tls case AUDIO_ENCODING_SLINEAR:
225 1.7.8.1 tls #endif
226 1.7.8.1 tls if (wi->precision == 16)
227 1.7.8.1 tls conv_func = swap_bytes;
228 1.7.8.1 tls else if (wi->precision == 32)
229 1.7.8.1 tls conv_func = swap_bytes32;
230 1.7.8.1 tls break;
231 1.7.8.1 tls }
232 1.7.8.1 tls
233 1.7.8.1 tls return conv_func;
234 1.7.8.1 tls }
235