OpenBSD-4.6/usr.bin/aucat/aparams.c

Compare this file to the similar file:
Show the results in this format:

/*	$OpenBSD: aparams.c,v 1.6 2009/01/23 17:38:15 ratchov Exp $	*/
/*
 * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "aparams.h"

int aparams_ctltovol[128] = {
	    0,
	  256,	  266,	  276,	  287,	  299,	  310,	  323,	  335,
	  348,	  362,	  376,	  391,	  406,	  422,	  439,	  456,
	  474,	  493,	  512,	  532,	  553,	  575,	  597,	  621,
	  645,	  670,	  697,	  724,	  753,	  782,	  813,	  845,
	  878,	  912,	  948,	  985,	 1024,	 1064,	 1106,	 1149,
	 1195,	 1241,	 1290,	 1341,	 1393,	 1448,	 1505,	 1564,
	 1625,	 1689,	 1756,	 1825,	 1896,	 1971,	 2048,	 2128,
	 2212,	 2299,	 2389,	 2483,	 2580,	 2682,	 2787,	 2896,
	 3010,	 3128,	 3251,	 3379,	 3511,	 3649,	 3792,	 3941,
	 4096,	 4257,	 4424,	 4598,	 4778,	 4966,	 5161,	 5363,
	 5574,	 5793,	 6020,	 6256,	 6502,	 6757,	 7023,	 7298,
	 7585,	 7883,	 8192,	 8514,	 8848,	 9195,	 9556,	 9931,
	10321,	10726,	11148,	11585,	12040,	12513,	13004,	13515,
	14045,	14596,	15170,	15765,	16384,	17027,	17696,	18390,
	19112,	19863,	20643,	21453,	22295,	23170,	24080,	25025,
	26008,	27029,	28090,	29193,	30339,	31530,	32768
};

/*
 * Generate a string corresponding to the encoding in par,
 * return the length of the resulting string
 */
int
aparams_enctostr(struct aparams *par, char *ostr)
{
	char *p = ostr;

	*p++ = par->sig ? 's' : 'u';
	if (par->bits > 9)
		*p++ = '0' + par->bits / 10;
	*p++ = '0' + par->bits % 10;
	if (par->bps > 1) {
		*p++ = par->le ? 'l' : 'b';
		*p++ = 'e';
		if (par->bps != APARAMS_BPS(par->bits) ||
		    par->bits < par->bps * 8) {
			*p++ = par->bps + '0';
			if (par->bits < par->bps * 8) {
				*p++ = par->msb ? 'm' : 'l';
				*p++ = 's';
				*p++ = 'b';
			}
		}
	}
	*p++ = '\0';
	return p - ostr - 1;
}

/*
 * Parse an encoding string, examples: s8, u8, s16, s16le, s24be ...
 * set *istr to the char following the encoding. Retrun the number
 * of bytes consumed
 */
int
aparams_strtoenc(struct aparams *par, char *istr)
{
	char *p = istr;
	int i, sig, bits, le, bps, msb;

#define IS_SEP(c)			\
	(((c) < 'a' || (c) > 'z') &&	\
	 ((c) < 'A' || (c) > 'Z') &&	\
	 ((c) < '0' || (c) > '9'))

	/*
	 * get signedness
	 */
	if (*p == 's') {
		sig = 1;
	} else if (*p == 'u') {
		sig = 0;
	} else
		return 0;
	p++;

	/*
	 * get number of bits per sample
	 */
	bits = 0;
	for (i = 0; i < 2; i++) {
		if (*p < '0' || *p > '9')
			break;
		bits = (bits * 10) + *p - '0';
		p++;
	}
	if (bits < BITS_MIN || bits > BITS_MAX)
		return 0;
	bps = APARAMS_BPS(bits);
	msb = 1;
	le = NATIVE_LE;

	/*
	 * get (optionnal) endianness
	 */
	if (p[0] == 'l' && p[1] == 'e') {
		le = 1;
		p += 2;
	} else if (p[0] == 'b' && p[1] == 'e') {
		le = 0;
		p += 2;
	} else if (IS_SEP(*p)) {
		goto done;
	} else
		return 0;

	/*
	 * get (optionnal) number of bytes
	 */
	if (*p >= '0' && *p <= '9') {
		bps = *p - '0';
		if (bps < (bits + 7) / 8 ||
		    bps > (BITS_MAX + 7) / 8)
			return 0;
		p++;

		/*
		 * get (optionnal) alignement
		 */
		if (p[0] == 'm' && p[1] == 's' && p[2] == 'b') {
			msb = 1;
			p += 3;
		} else if (p[0] == 'l' && p[1] == 's' && p[2] == 'b') {
			msb = 0;
			p += 3;
		} else if (IS_SEP(*p)) {
			goto done;
		} else
			return 0;
	} else if (!IS_SEP(*p))
		return 0;

done:
       	par->msb = msb;
	par->sig = sig;
	par->bits = bits;
	par->bps = bps;
	par->le = le;
	return p - istr;
}

/*
 * Initialise parameters structure with the defaults natively supported
 * by the machine.
 */
void
aparams_init(struct aparams *par, unsigned cmin, unsigned cmax, unsigned rate)
{
	par->bps = 2;		/* 2 bytes per sample */
	par->bits = 16;		/* 16 significant bits per sample */
	par->sig = 1;		/* samples are signed */
	par->le = NATIVE_LE;
	par->msb = 1;		/* msb justified */
	par->cmin = cmin;
	par->cmax = cmax;
	par->rate = rate;
}

/*
 * Print the format/channels/encoding on stderr.
 */
void
aparams_print(struct aparams *par)
{
	char enc[ENCMAX];

	aparams_enctostr(par, enc);
	fprintf(stderr, "%s", enc);
	fprintf(stderr, ",%u:%u", par->cmin, par->cmax);
	fprintf(stderr, ",%uHz", par->rate);
}

void
aparams_print2(struct aparams *par1, struct aparams *par2)
{
	aparams_print(par1);
	fprintf(stderr, " -> ");
	aparams_print(par2);
}

/*
 * Return true if both encodings are the same.
 */
int
aparams_eqenc(struct aparams *par1, struct aparams *par2)
{
	if (par1->bps != par2->bps ||
	    par1->bits != par2->bits ||
	    par1->sig != par2->sig)
		return 0;
	if ((par1->bits != 8 * par1->bps) && par1->msb != par2->msb)
		return 0;
	if (par1->bps > 1 && par1->le != par2->le)
		return 0;
	return 1;
}

/*
 * Return true if both parameters are the same.
 */
int
aparams_eq(struct aparams *par1, struct aparams *par2)
{
	if (!aparams_eqenc(par1, par2) ||
	    par1->cmin != par2->cmin ||
	    par1->cmax != par2->cmax ||
	    par1->rate != par2->rate)
		return 0;
	return 1;
}

/*
 * Retrurn true if first channel range includes second range
 */
int
aparams_subset(struct aparams *subset, struct aparams *set)
{
	return subset->cmin >= set->cmin && subset->cmax <= set->cmax;
}

/*
 * grow channels range and sample rate of ``set'' in order ``subset'' to
 * become an actual subset of it.
 */
void
aparams_grow(struct aparams *set, struct aparams *subset)
{
	if (set->cmin > subset->cmin)
		set->cmin = subset->cmin;
	if (set->cmax < subset->cmax)
		set->cmax = subset->cmax;
	if (set->rate < subset->rate)
		set->rate = subset->rate;
}

/*
 * Return true if rates are the same
 */
int
aparams_eqrate(struct aparams *p1, struct aparams *p2)
{
	/* XXX: allow 1/9 halftone of difference */
	return p1->rate == p2->rate;
}


/*
 * Return the number of bytes per frame with the given parameters.
 */
unsigned
aparams_bpf(struct aparams *par)
{
	return (par->cmax - par->cmin + 1) * par->bps;
}

void
aparams_copyenc(struct aparams *dst, struct aparams *src)
{
	dst->sig = src->sig;
	dst->le = src->le;
	dst->msb = src->msb;
	dst->bits = src->bits;
	dst->bps = src->bps;
}