sun.c revision 1.9 1 1.9 mrg /* $NetBSD: sun.c,v 1.9 2015/08/05 06:54:39 mrg 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.9 mrg __RCSID("$NetBSD: sun.c,v 1.9 2015/08/05 06:54:39 mrg 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.8 mrg #include <unistd.h>
50 1.1 mrg
51 1.1 mrg #include "libaudio.h"
52 1.8 mrg #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.8 mrg
112 1.8 mrg int
113 1.9 mrg sun_prepare_header(struct track_info *ti, void **hdrp, size_t *lenp, int *leftp)
114 1.8 mrg {
115 1.8 mrg static int warned = 0;
116 1.8 mrg static sun_audioheader auh;
117 1.9 mrg int sunenc, oencoding = ti->encoding;
118 1.8 mrg
119 1.8 mrg /* only perform conversions if we don't specify the encoding */
120 1.9 mrg switch (ti->encoding) {
121 1.8 mrg
122 1.8 mrg case AUDIO_ENCODING_ULINEAR_LE:
123 1.8 mrg #if BYTE_ORDER == LITTLE_ENDIAN
124 1.8 mrg case AUDIO_ENCODING_ULINEAR:
125 1.8 mrg #endif
126 1.9 mrg if (ti->precision == 16 || ti->precision == 32)
127 1.9 mrg ti->encoding = AUDIO_ENCODING_SLINEAR_BE;
128 1.8 mrg break;
129 1.8 mrg
130 1.8 mrg case AUDIO_ENCODING_ULINEAR_BE:
131 1.8 mrg #if BYTE_ORDER == BIG_ENDIAN
132 1.8 mrg case AUDIO_ENCODING_ULINEAR:
133 1.8 mrg #endif
134 1.9 mrg if (ti->precision == 16 || ti->precision == 32)
135 1.9 mrg ti->encoding = AUDIO_ENCODING_SLINEAR_BE;
136 1.8 mrg break;
137 1.8 mrg
138 1.8 mrg case AUDIO_ENCODING_SLINEAR_LE:
139 1.8 mrg #if BYTE_ORDER == LITTLE_ENDIAN
140 1.8 mrg case AUDIO_ENCODING_SLINEAR:
141 1.8 mrg #endif
142 1.9 mrg if (ti->precision == 16 || ti->precision == 32)
143 1.9 mrg ti->encoding = AUDIO_ENCODING_SLINEAR_BE;
144 1.8 mrg break;
145 1.8 mrg
146 1.8 mrg #if BYTE_ORDER == BIG_ENDIAN
147 1.8 mrg case AUDIO_ENCODING_SLINEAR:
148 1.9 mrg ti->encoding = AUDIO_ENCODING_SLINEAR_BE;
149 1.8 mrg break;
150 1.8 mrg #endif
151 1.8 mrg }
152 1.8 mrg
153 1.8 mrg /* if we can't express this as a Sun header, don't write any */
154 1.9 mrg if (audio_encoding_to_sun(ti->encoding, ti->precision, &sunenc) != 0) {
155 1.9 mrg if (!ti->qflag && !warned) {
156 1.8 mrg const char *s = audio_enc_from_val(oencoding);
157 1.8 mrg
158 1.8 mrg if (s == NULL)
159 1.8 mrg s = "(unknown)";
160 1.8 mrg warnx("failed to convert to sun encoding from %s "
161 1.8 mrg "(precision %d);\nSun audio header not written",
162 1.9 mrg s, ti->precision);
163 1.8 mrg }
164 1.9 mrg ti->format = AUDIO_FORMAT_NONE;
165 1.8 mrg warned = 1;
166 1.8 mrg return -1;
167 1.8 mrg }
168 1.8 mrg
169 1.8 mrg auh.magic = htonl(AUDIO_FILE_MAGIC);
170 1.9 mrg if (ti->outfd == STDOUT_FILENO)
171 1.8 mrg auh.data_size = htonl(AUDIO_UNKNOWN_SIZE);
172 1.9 mrg else if (ti->total_size != -1)
173 1.9 mrg auh.data_size = htonl(ti->total_size);
174 1.8 mrg else
175 1.8 mrg auh.data_size = 0;
176 1.8 mrg auh.encoding = htonl(sunenc);
177 1.9 mrg auh.sample_rate = htonl(ti->sample_rate);
178 1.9 mrg auh.channels = htonl(ti->channels);
179 1.9 mrg if (ti->header_info) {
180 1.8 mrg int len, infolen;
181 1.8 mrg
182 1.9 mrg infolen = ((len = strlen(ti->header_info)) + 7) & 0xfffffff8;
183 1.8 mrg *leftp = infolen - len;
184 1.8 mrg auh.hdr_size = htonl(sizeof(auh) + infolen);
185 1.8 mrg } else {
186 1.8 mrg *leftp = sizeof(audio_default_info);
187 1.8 mrg auh.hdr_size = htonl(sizeof(auh) + *leftp);
188 1.8 mrg }
189 1.8 mrg *(sun_audioheader **)hdrp = &auh;
190 1.8 mrg *lenp = sizeof auh;
191 1.8 mrg return 0;
192 1.8 mrg }
193 1.8 mrg
194 1.8 mrg write_conv_func
195 1.9 mrg sun_write_get_conv_func(struct track_info *ti)
196 1.8 mrg {
197 1.8 mrg write_conv_func conv_func = NULL;
198 1.8 mrg
199 1.8 mrg /* only perform conversions if we don't specify the encoding */
200 1.9 mrg switch (ti->encoding) {
201 1.8 mrg
202 1.8 mrg case AUDIO_ENCODING_ULINEAR_LE:
203 1.8 mrg #if BYTE_ORDER == LITTLE_ENDIAN
204 1.8 mrg case AUDIO_ENCODING_ULINEAR:
205 1.8 mrg #endif
206 1.9 mrg if (ti->precision == 16)
207 1.8 mrg conv_func = change_sign16_swap_bytes_le;
208 1.9 mrg else if (ti->precision == 32)
209 1.8 mrg conv_func = change_sign32_swap_bytes_le;
210 1.8 mrg break;
211 1.8 mrg
212 1.8 mrg case AUDIO_ENCODING_ULINEAR_BE:
213 1.8 mrg #if BYTE_ORDER == BIG_ENDIAN
214 1.8 mrg case AUDIO_ENCODING_ULINEAR:
215 1.8 mrg #endif
216 1.9 mrg if (ti->precision == 16)
217 1.8 mrg conv_func = change_sign16_be;
218 1.9 mrg else if (ti->precision == 32)
219 1.8 mrg conv_func = change_sign32_be;
220 1.8 mrg break;
221 1.8 mrg
222 1.8 mrg case AUDIO_ENCODING_SLINEAR_LE:
223 1.8 mrg #if BYTE_ORDER == LITTLE_ENDIAN
224 1.8 mrg case AUDIO_ENCODING_SLINEAR:
225 1.8 mrg #endif
226 1.9 mrg if (ti->precision == 16)
227 1.8 mrg conv_func = swap_bytes;
228 1.9 mrg else if (ti->precision == 32)
229 1.8 mrg conv_func = swap_bytes32;
230 1.8 mrg break;
231 1.8 mrg }
232 1.8 mrg
233 1.8 mrg return conv_func;
234 1.8 mrg }
235