xref: /illumos-gate/usr/src/cmd/audio/utilities/AudioHdr.cc (revision 355b4669e025ff377602b6fc7caaf30dbc218371)
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.
35 AudioEndian 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
54 void AudioHdr::
55 Clear()
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?
66 AudioError AudioHdr::
67 Validate() 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.
121 Double AudioHdr::
122 Bytes_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.
139 off_t AudioHdr::
140 Time_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.
158 off_t AudioHdr::
159 Bytes_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.
171 size_t AudioHdr::
172 Bytes_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.
185 Double AudioHdr::
186 Samples_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.
198 unsigned long AudioHdr::
199 Time_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.
211 unsigned int AudioHdr::
212 FrameLength() const
213 {
214 	return (bytes_per_unit * channels);
215 }
216