Home | History | Annotate | Line # | Download | only in common
sun.c revision 1.10.8.1
      1  1.10.8.1    martin /*	$NetBSD: sun.c,v 1.10.8.1 2024/03/12 10:04:22 martin 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.10.8.1    martin __RCSID("$NetBSD: sun.c,v 1.10.8.1 2024/03/12 10:04:22 martin 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.10.8.1    martin 
    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