1 1.11 gson /* $NetBSD: sun.c,v 1.11 2024/02/27 21:05:34 gson Exp $ */ 2 1.1 mrg 3 1.1 mrg /* 4 1.10 mrg * Copyright (c) 2002, 2013, 2015 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.11 gson __RCSID("$NetBSD: sun.c,v 1.11 2024/02/27 21:05:34 gson 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.11 gson 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