17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bdstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bdstevel@tonic-gate * (the "License").  You may not use this file except in compliance
77c478bdstevel@tonic-gate * with the License.
87c478bdstevel@tonic-gate *
97c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bdstevel@tonic-gate * See the License for the specific language governing permissions
127c478bdstevel@tonic-gate * and limitations under the License.
137c478bdstevel@tonic-gate *
147c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bdstevel@tonic-gate *
207c478bdstevel@tonic-gate * CDDL HEADER END
217c478bdstevel@tonic-gate */
227c478bdstevel@tonic-gate/*
237c478bdstevel@tonic-gate * Copyright (c) 1992-2001 by Sun Microsystems, Inc.
247c478bdstevel@tonic-gate * All rights reserved.
257c478bdstevel@tonic-gate */
267c478bdstevel@tonic-gate
277c478bdstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bdstevel@tonic-gate
297c478bdstevel@tonic-gate#include <AudioHdr.h>
307c478bdstevel@tonic-gate
317c478bdstevel@tonic-gate// class AudioHdr basic methods
327c478bdstevel@tonic-gate
337c478bdstevel@tonic-gate// This routine uses the byteorder network utilities to tell whether the
347c478bdstevel@tonic-gate// current process uses network byte order or not.
357c478bdstevel@tonic-gateAudioEndian AudioHdr::localByteOrder() const
367c478bdstevel@tonic-gate{
377c478bdstevel@tonic-gate	short sTestHost;
387c478bdstevel@tonic-gate	short sTestNetwork;
397c478bdstevel@tonic-gate	static AudioEndian ae = UNDEFINED_ENDIAN;
407c478bdstevel@tonic-gate
417c478bdstevel@tonic-gate	if (ae == UNDEFINED_ENDIAN) {
427c478bdstevel@tonic-gate		sTestHost = MAXSHORT;
437c478bdstevel@tonic-gate		sTestNetwork = htons(sTestHost);
447c478bdstevel@tonic-gate		if (sTestNetwork != sTestHost) {
457c478bdstevel@tonic-gate			ae = LITTLE_ENDIAN;
467c478bdstevel@tonic-gate		} else {
477c478bdstevel@tonic-gate			ae = BIG_ENDIAN;
487c478bdstevel@tonic-gate		}
497c478bdstevel@tonic-gate	}
507c478bdstevel@tonic-gate	return (ae);
517c478bdstevel@tonic-gate}
527c478bdstevel@tonic-gate
537c478bdstevel@tonic-gate// Clear a header structure
547c478bdstevel@tonic-gatevoid AudioHdr::
557c478bdstevel@tonic-gateClear()
567c478bdstevel@tonic-gate{
577c478bdstevel@tonic-gate	sample_rate = 0;
587c478bdstevel@tonic-gate	samples_per_unit = 0;
597c478bdstevel@tonic-gate	bytes_per_unit = 0;
607c478bdstevel@tonic-gate	channels = 0;
617c478bdstevel@tonic-gate	encoding = NONE;
627c478bdstevel@tonic-gate}
637c478bdstevel@tonic-gate
647c478bdstevel@tonic-gate// Return error code (TRUE) if header is inconsistent or unrecognizable
657c478bdstevel@tonic-gate// XXX - how do we support extensions?
667c478bdstevel@tonic-gateAudioError AudioHdr::
677c478bdstevel@tonic-gateValidate() const
687c478bdstevel@tonic-gate{
697c478bdstevel@tonic-gate	// Check for uninitialized fields
707c478bdstevel@tonic-gate	if ((bytes_per_unit < 1) || (samples_per_unit < 1) ||
717c478bdstevel@tonic-gate	    (sample_rate < 1) || (channels < 1))
727c478bdstevel@tonic-gate		return (AUDIO_ERR_BADHDR);
737c478bdstevel@tonic-gate
747c478bdstevel@tonic-gate	switch (encoding) {
757c478bdstevel@tonic-gate	case NONE:
767c478bdstevel@tonic-gate		return (AUDIO_ERR_BADHDR);
777c478bdstevel@tonic-gate
787c478bdstevel@tonic-gate	case LINEAR:
797c478bdstevel@tonic-gate		if (bytes_per_unit > 4)
807c478bdstevel@tonic-gate			return (AUDIO_ERR_PRECISION);
817c478bdstevel@tonic-gate		if (samples_per_unit != 1)
827c478bdstevel@tonic-gate			return (AUDIO_ERR_HDRINVAL);
837c478bdstevel@tonic-gate		break;
847c478bdstevel@tonic-gate
857c478bdstevel@tonic-gate	case FLOAT:
867c478bdstevel@tonic-gate		if ((bytes_per_unit != 4) && (bytes_per_unit != 8))
877c478bdstevel@tonic-gate			return (AUDIO_ERR_PRECISION);
887c478bdstevel@tonic-gate		if (samples_per_unit != 1)
897c478bdstevel@tonic-gate			return (AUDIO_ERR_HDRINVAL);
907c478bdstevel@tonic-gate		break;
917c478bdstevel@tonic-gate
927c478bdstevel@tonic-gate	case ULAW:
937c478bdstevel@tonic-gate	case ALAW:
947c478bdstevel@tonic-gate	case G722:
957c478bdstevel@tonic-gate		if (bytes_per_unit != 1)
967c478bdstevel@tonic-gate			return (AUDIO_ERR_PRECISION);
977c478bdstevel@tonic-gate		if (samples_per_unit != 1)
987c478bdstevel@tonic-gate			return (AUDIO_ERR_HDRINVAL);
997c478bdstevel@tonic-gate		break;
1007c478bdstevel@tonic-gate
1017c478bdstevel@tonic-gate	case G721:
1027c478bdstevel@tonic-gate	case DVI:
1037c478bdstevel@tonic-gate		// G.721 is a 4-bit encoding
1047c478bdstevel@tonic-gate		if ((bytes_per_unit != 1) || (samples_per_unit != 2))
1057c478bdstevel@tonic-gate			return (AUDIO_ERR_PRECISION);
1067c478bdstevel@tonic-gate		break;
1077c478bdstevel@tonic-gate
1087c478bdstevel@tonic-gate	case G723:
1097c478bdstevel@tonic-gate		// G.723 has 3-bit and 5-bit flavors
1107c478bdstevel@tonic-gate		// 5-bit is currently unsupported
1117c478bdstevel@tonic-gate		if ((bytes_per_unit != 3) || (samples_per_unit != 8))
1127c478bdstevel@tonic-gate			return (AUDIO_ERR_PRECISION);
1137c478bdstevel@tonic-gate		break;
1147c478bdstevel@tonic-gate	}
1157c478bdstevel@tonic-gate	return (AUDIO_SUCCESS);
1167c478bdstevel@tonic-gate}
1177c478bdstevel@tonic-gate
1187c478bdstevel@tonic-gate
1197c478bdstevel@tonic-gate// Convert a byte count into a floating-point time value, in seconds,
1207c478bdstevel@tonic-gate// using the encoding specified in the audio header.
1217c478bdstevel@tonic-gateDouble AudioHdr::
1227c478bdstevel@tonic-gateBytes_to_Time(
1237c478bdstevel@tonic-gate	off_t	cnt) const			// byte count
1247c478bdstevel@tonic-gate{
1257c478bdstevel@tonic-gate	if ((cnt == AUDIO_UNKNOWN_SIZE) || (Validate() != AUDIO_SUCCESS))
1267c478bdstevel@tonic-gate		return (AUDIO_UNKNOWN_TIME);
1277c478bdstevel@tonic-gate
1287c478bdstevel@tonic-gate	// round off to nearest sample frame!
1297c478bdstevel@tonic-gate	cnt -= (cnt % (bytes_per_unit * channels));
1307c478bdstevel@tonic-gate
1317c478bdstevel@tonic-gate	return (Double) ((double)cnt /
1327c478bdstevel@tonic-gate	    ((double)(channels * bytes_per_unit * sample_rate) /
1337c478bdstevel@tonic-gate	    (double)samples_per_unit));
1347c478bdstevel@tonic-gate}
1357c478bdstevel@tonic-gate
1367c478bdstevel@tonic-gate// Convert a floating-point time value, in seconds, to a byte count for
1377c478bdstevel@tonic-gate// the audio encoding in the audio header.  Make sure that the byte count
1387c478bdstevel@tonic-gate// or offset does not span a sample frame.
1397c478bdstevel@tonic-gateoff_t AudioHdr::
1407c478bdstevel@tonic-gateTime_to_Bytes(
1417c478bdstevel@tonic-gate	Double	sec) const			// time, in seconds
1427c478bdstevel@tonic-gate{
1437c478bdstevel@tonic-gate	off_t	offset;
1447c478bdstevel@tonic-gate
1457c478bdstevel@tonic-gate	if (Undefined(sec) || (Validate() != AUDIO_SUCCESS))
1467c478bdstevel@tonic-gate		return (AUDIO_UNKNOWN_SIZE);
1477c478bdstevel@tonic-gate
1487c478bdstevel@tonic-gate	offset = (off_t)(0.5 + (sec *
1497c478bdstevel@tonic-gate	    ((double)(channels * bytes_per_unit * sample_rate) /
1507c478bdstevel@tonic-gate	    (double)samples_per_unit)));
1517c478bdstevel@tonic-gate
1527c478bdstevel@tonic-gate	// Round down to the start of the nearest sample frame
1537c478bdstevel@tonic-gate	offset -= (offset % (bytes_per_unit * channels));
1547c478bdstevel@tonic-gate	return (offset);
1557c478bdstevel@tonic-gate}
1567c478bdstevel@tonic-gate
1577c478bdstevel@tonic-gate// Round a byte count down to a sample frame boundary.
1587c478bdstevel@tonic-gateoff_t AudioHdr::
1597c478bdstevel@tonic-gateBytes_to_Bytes(
1607c478bdstevel@tonic-gate	off_t&	cnt) const
1617c478bdstevel@tonic-gate{
1627c478bdstevel@tonic-gate	if (Validate() != AUDIO_SUCCESS)
1637c478bdstevel@tonic-gate		return (AUDIO_UNKNOWN_SIZE);
1647c478bdstevel@tonic-gate
1657c478bdstevel@tonic-gate	// Round down to the start of the nearest sample frame
1667c478bdstevel@tonic-gate	cnt -= (cnt % (bytes_per_unit * channels));
1677c478bdstevel@tonic-gate	return (cnt);
1687c478bdstevel@tonic-gate}
1697c478bdstevel@tonic-gate
1707c478bdstevel@tonic-gate// Round a byte count down to a sample frame boundary.
1717c478bdstevel@tonic-gatesize_t AudioHdr::
1727c478bdstevel@tonic-gateBytes_to_Bytes(
1737c478bdstevel@tonic-gate	size_t&	cnt) const
1747c478bdstevel@tonic-gate{
1757c478bdstevel@tonic-gate	if (Validate() != AUDIO_SUCCESS)
1767c478bdstevel@tonic-gate		return (AUDIO_UNKNOWN_SIZE);
1777c478bdstevel@tonic-gate
1787c478bdstevel@tonic-gate	// Round down to the start of the nearest sample frame
1797c478bdstevel@tonic-gate	cnt -= (cnt % (bytes_per_unit * channels));
1807c478bdstevel@tonic-gate	return (cnt);
1817c478bdstevel@tonic-gate}
1827c478bdstevel@tonic-gate
1837c478bdstevel@tonic-gate// Convert a count of sample frames into a floating-point time value,
1847c478bdstevel@tonic-gate// in seconds, using the encoding specified in the audio header.
1857c478bdstevel@tonic-gateDouble AudioHdr::
1867c478bdstevel@tonic-gateSamples_to_Time(
1877c478bdstevel@tonic-gate	unsigned long	cnt) const		// sample frame count
1887c478bdstevel@tonic-gate{
1897c478bdstevel@tonic-gate	if ((cnt == AUDIO_UNKNOWN_SIZE) || (Validate() != AUDIO_SUCCESS))
1907c478bdstevel@tonic-gate		return (AUDIO_UNKNOWN_TIME);
1917c478bdstevel@tonic-gate
1927c478bdstevel@tonic-gate	return ((Double)(((double)cnt * (double)samples_per_unit) /
1937c478bdstevel@tonic-gate	    (double)sample_rate));
1947c478bdstevel@tonic-gate}
1957c478bdstevel@tonic-gate
1967c478bdstevel@tonic-gate// Convert a floating-point time value, in seconds, to a count of sample frames
1977c478bdstevel@tonic-gate// for the audio encoding in the audio header.
1987c478bdstevel@tonic-gateunsigned long AudioHdr::
1997c478bdstevel@tonic-gateTime_to_Samples(
2007c478bdstevel@tonic-gate	Double	sec) const			// time, in seconds
2017c478bdstevel@tonic-gate{
2027c478bdstevel@tonic-gate	if (Undefined(sec) || (Validate() != AUDIO_SUCCESS))
2037c478bdstevel@tonic-gate		return (AUDIO_UNKNOWN_SIZE);
2047c478bdstevel@tonic-gate
2057c478bdstevel@tonic-gate	// Round down to sample frame boundary
2067c478bdstevel@tonic-gate	return ((unsigned long) (AUDIO_MINFLOAT +
2077c478bdstevel@tonic-gate	    (((double)sec * (double)sample_rate) / (double)samples_per_unit)));
2087c478bdstevel@tonic-gate}
2097c478bdstevel@tonic-gate
2107c478bdstevel@tonic-gate// Return the number of bytes in a sample frame for the audio encoding.
2117c478bdstevel@tonic-gateunsigned int AudioHdr::
2127c478bdstevel@tonic-gateFrameLength() const
2137c478bdstevel@tonic-gate{
2147c478bdstevel@tonic-gate	return (bytes_per_unit * channels);
2157c478bdstevel@tonic-gate}
216