1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright (c) 1992-2001 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <AudioHdr.h>
30
31// class AudioHdr basic methods
32
33// This routine uses the byteorder network utilities to tell whether the
34// current process uses network byte order or not.
35AudioEndian AudioHdr::localByteOrder() const
36{
37	short sTestHost;
38	short sTestNetwork;
39	static AudioEndian ae = UNDEFINED_ENDIAN;
40
41	if (ae == UNDEFINED_ENDIAN) {
42		sTestHost = MAXSHORT;
43		sTestNetwork = htons(sTestHost);
44		if (sTestNetwork != sTestHost) {
45			ae = LITTLE_ENDIAN;
46		} else {
47			ae = BIG_ENDIAN;
48		}
49	}
50	return (ae);
51}
52
53// Clear a header structure
54void AudioHdr::
55Clear()
56{
57	sample_rate = 0;
58	samples_per_unit = 0;
59	bytes_per_unit = 0;
60	channels = 0;
61	encoding = NONE;
62}
63
64// Return error code (TRUE) if header is inconsistent or unrecognizable
65// XXX - how do we support extensions?
66AudioError AudioHdr::
67Validate() const
68{
69	// Check for uninitialized fields
70	if ((bytes_per_unit < 1) || (samples_per_unit < 1) ||
71	    (sample_rate < 1) || (channels < 1))
72		return (AUDIO_ERR_BADHDR);
73
74	switch (encoding) {
75	case NONE:
76		return (AUDIO_ERR_BADHDR);
77
78	case LINEAR:
79		if (bytes_per_unit > 4)
80			return (AUDIO_ERR_PRECISION);
81		if (samples_per_unit != 1)
82			return (AUDIO_ERR_HDRINVAL);
83		break;
84
85	case FLOAT:
86		if ((bytes_per_unit != 4) && (bytes_per_unit != 8))
87			return (AUDIO_ERR_PRECISION);
88		if (samples_per_unit != 1)
89			return (AUDIO_ERR_HDRINVAL);
90		break;
91
92	case ULAW:
93	case ALAW:
94	case G722:
95		if (bytes_per_unit != 1)
96			return (AUDIO_ERR_PRECISION);
97		if (samples_per_unit != 1)
98			return (AUDIO_ERR_HDRINVAL);
99		break;
100
101	case G721:
102	case DVI:
103		// G.721 is a 4-bit encoding
104		if ((bytes_per_unit != 1) || (samples_per_unit != 2))
105			return (AUDIO_ERR_PRECISION);
106		break;
107
108	case G723:
109		// G.723 has 3-bit and 5-bit flavors
110		// 5-bit is currently unsupported
111		if ((bytes_per_unit != 3) || (samples_per_unit != 8))
112			return (AUDIO_ERR_PRECISION);
113		break;
114	}
115	return (AUDIO_SUCCESS);
116}
117
118
119// Convert a byte count into a floating-point time value, in seconds,
120// using the encoding specified in the audio header.
121Double AudioHdr::
122Bytes_to_Time(
123	off_t	cnt) const			// byte count
124{
125	if ((cnt == AUDIO_UNKNOWN_SIZE) || (Validate() != AUDIO_SUCCESS))
126		return (AUDIO_UNKNOWN_TIME);
127
128	// round off to nearest sample frame!
129	cnt -= (cnt % (bytes_per_unit * channels));
130
131	return (Double) ((double)cnt /
132	    ((double)(channels * bytes_per_unit * sample_rate) /
133	    (double)samples_per_unit));
134}
135
136// Convert a floating-point time value, in seconds, to a byte count for
137// the audio encoding in the audio header.  Make sure that the byte count
138// or offset does not span a sample frame.
139off_t AudioHdr::
140Time_to_Bytes(
141	Double	sec) const			// time, in seconds
142{
143	off_t	offset;
144
145	if (Undefined(sec) || (Validate() != AUDIO_SUCCESS))
146		return (AUDIO_UNKNOWN_SIZE);
147
148	offset = (off_t)(0.5 + (sec *
149	    ((double)(channels * bytes_per_unit * sample_rate) /
150	    (double)samples_per_unit)));
151
152	// Round down to the start of the nearest sample frame
153	offset -= (offset % (bytes_per_unit * channels));
154	return (offset);
155}
156
157// Round a byte count down to a sample frame boundary.
158off_t AudioHdr::
159Bytes_to_Bytes(
160	off_t&	cnt) const
161{
162	if (Validate() != AUDIO_SUCCESS)
163		return (AUDIO_UNKNOWN_SIZE);
164
165	// Round down to the start of the nearest sample frame
166	cnt -= (cnt % (bytes_per_unit * channels));
167	return (cnt);
168}
169
170// Round a byte count down to a sample frame boundary.
171size_t AudioHdr::
172Bytes_to_Bytes(
173	size_t&	cnt) const
174{
175	if (Validate() != AUDIO_SUCCESS)
176		return (AUDIO_UNKNOWN_SIZE);
177
178	// Round down to the start of the nearest sample frame
179	cnt -= (cnt % (bytes_per_unit * channels));
180	return (cnt);
181}
182
183// Convert a count of sample frames into a floating-point time value,
184// in seconds, using the encoding specified in the audio header.
185Double AudioHdr::
186Samples_to_Time(
187	unsigned long	cnt) const		// sample frame count
188{
189	if ((cnt == AUDIO_UNKNOWN_SIZE) || (Validate() != AUDIO_SUCCESS))
190		return (AUDIO_UNKNOWN_TIME);
191
192	return ((Double)(((double)cnt * (double)samples_per_unit) /
193	    (double)sample_rate));
194}
195
196// Convert a floating-point time value, in seconds, to a count of sample frames
197// for the audio encoding in the audio header.
198unsigned long AudioHdr::
199Time_to_Samples(
200	Double	sec) const			// time, in seconds
201{
202	if (Undefined(sec) || (Validate() != AUDIO_SUCCESS))
203		return (AUDIO_UNKNOWN_SIZE);
204
205	// Round down to sample frame boundary
206	return ((unsigned long) (AUDIO_MINFLOAT +
207	    (((double)sec * (double)sample_rate) / (double)samples_per_unit)));
208}
209
210// Return the number of bytes in a sample frame for the audio encoding.
211unsigned int AudioHdr::
212FrameLength() const
213{
214	return (bytes_per_unit * channels);
215}
216