xref: /illumos-gate/usr/src/cmd/audio/utilities/AudioHdr.cc (revision 2a8bcb4efb45d99ac41c94a75c396b362c414f7f)
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 #include <AudioHdr.h>
28 
29 // class AudioHdr basic methods
30 
31 // This routine uses the byteorder network utilities to tell whether the
32 // current process uses network byte order or not.
localByteOrder() const33 AudioEndian AudioHdr::localByteOrder() const
34 {
35 	short sTestHost;
36 	short sTestNetwork;
37 	static AudioEndian ae = UNDEFINED_ENDIAN;
38 
39 	if (ae == UNDEFINED_ENDIAN) {
40 		sTestHost = MAXSHORT;
41 		sTestNetwork = htons(sTestHost);
42 		if (sTestNetwork != sTestHost) {
43 			ae = LITTLE_ENDIAN;
44 		} else {
45 			ae = BIG_ENDIAN;
46 		}
47 	}
48 	return (ae);
49 }
50 
51 // Clear a header structure
52 void AudioHdr::
Clear()53 Clear()
54 {
55 	sample_rate = 0;
56 	samples_per_unit = 0;
57 	bytes_per_unit = 0;
58 	channels = 0;
59 	encoding = NONE;
60 }
61 
62 // Return error code (TRUE) if header is inconsistent or unrecognizable
63 // XXX - how do we support extensions?
64 AudioError AudioHdr::
Validate() const65 Validate() const
66 {
67 	// Check for uninitialized fields
68 	if ((bytes_per_unit < 1) || (samples_per_unit < 1) ||
69 	    (sample_rate < 1) || (channels < 1))
70 		return (AUDIO_ERR_BADHDR);
71 
72 	switch (encoding) {
73 	case NONE:
74 		return (AUDIO_ERR_BADHDR);
75 
76 	case LINEAR:
77 		if (bytes_per_unit > 4)
78 			return (AUDIO_ERR_PRECISION);
79 		if (samples_per_unit != 1)
80 			return (AUDIO_ERR_HDRINVAL);
81 		break;
82 
83 	case FLOAT:
84 		if ((bytes_per_unit != 4) && (bytes_per_unit != 8))
85 			return (AUDIO_ERR_PRECISION);
86 		if (samples_per_unit != 1)
87 			return (AUDIO_ERR_HDRINVAL);
88 		break;
89 
90 	case ULAW:
91 	case ALAW:
92 	case G722:
93 		if (bytes_per_unit != 1)
94 			return (AUDIO_ERR_PRECISION);
95 		if (samples_per_unit != 1)
96 			return (AUDIO_ERR_HDRINVAL);
97 		break;
98 
99 	case G721:
100 	case DVI:
101 		// G.721 is a 4-bit encoding
102 		if ((bytes_per_unit != 1) || (samples_per_unit != 2))
103 			return (AUDIO_ERR_PRECISION);
104 		break;
105 
106 	case G723:
107 		// G.723 has 3-bit and 5-bit flavors
108 		// 5-bit is currently unsupported
109 		if ((bytes_per_unit != 3) || (samples_per_unit != 8))
110 			return (AUDIO_ERR_PRECISION);
111 		break;
112 	}
113 	return (AUDIO_SUCCESS);
114 }
115 
116 
117 // Convert a byte count into a floating-point time value, in seconds,
118 // using the encoding specified in the audio header.
119 Double AudioHdr::
Bytes_to_Time(off_t cnt) const120 Bytes_to_Time(
121 	off_t	cnt) const			// byte count
122 {
123 	if ((cnt == AUDIO_UNKNOWN_SIZE) || (Validate() != AUDIO_SUCCESS))
124 		return (AUDIO_UNKNOWN_TIME);
125 
126 	// round off to nearest sample frame!
127 	cnt -= (cnt % (bytes_per_unit * channels));
128 
129 	return (Double) ((double)cnt /
130 	    ((double)(channels * bytes_per_unit * sample_rate) /
131 	    (double)samples_per_unit));
132 }
133 
134 // Convert a floating-point time value, in seconds, to a byte count for
135 // the audio encoding in the audio header.  Make sure that the byte count
136 // or offset does not span a sample frame.
137 off_t AudioHdr::
Time_to_Bytes(Double sec) const138 Time_to_Bytes(
139 	Double	sec) const			// time, in seconds
140 {
141 	off_t	offset;
142 
143 	if (Undefined(sec) || (Validate() != AUDIO_SUCCESS))
144 		return (AUDIO_UNKNOWN_SIZE);
145 
146 	offset = (off_t)(0.5 + (sec *
147 	    ((double)(channels * bytes_per_unit * sample_rate) /
148 	    (double)samples_per_unit)));
149 
150 	// Round down to the start of the nearest sample frame
151 	offset -= (offset % (bytes_per_unit * channels));
152 	return (offset);
153 }
154 
155 // Round a byte count down to a sample frame boundary.
156 off_t AudioHdr::
Bytes_to_Bytes(off_t & cnt) const157 Bytes_to_Bytes(
158 	off_t&	cnt) const
159 {
160 	if (Validate() != AUDIO_SUCCESS)
161 		return (AUDIO_UNKNOWN_SIZE);
162 
163 	// Round down to the start of the nearest sample frame
164 	cnt -= (cnt % (bytes_per_unit * channels));
165 	return (cnt);
166 }
167 
168 // Round a byte count down to a sample frame boundary.
169 size_t AudioHdr::
Bytes_to_Bytes(size_t & cnt) const170 Bytes_to_Bytes(
171 	size_t&	cnt) const
172 {
173 	if (Validate() != AUDIO_SUCCESS)
174 		return (AUDIO_UNKNOWN_SIZE);
175 
176 	// Round down to the start of the nearest sample frame
177 	cnt -= (cnt % (bytes_per_unit * channels));
178 	return (cnt);
179 }
180 
181 // Convert a count of sample frames into a floating-point time value,
182 // in seconds, using the encoding specified in the audio header.
183 Double AudioHdr::
Samples_to_Time(unsigned long cnt) const184 Samples_to_Time(
185 	unsigned long	cnt) const		// sample frame count
186 {
187 	if ((cnt == AUDIO_UNKNOWN_SIZE) || (Validate() != AUDIO_SUCCESS))
188 		return (AUDIO_UNKNOWN_TIME);
189 
190 	return ((Double)(((double)cnt * (double)samples_per_unit) /
191 	    (double)sample_rate));
192 }
193 
194 // Convert a floating-point time value, in seconds, to a count of sample frames
195 // for the audio encoding in the audio header.
196 unsigned long AudioHdr::
Time_to_Samples(Double sec) const197 Time_to_Samples(
198 	Double	sec) const			// time, in seconds
199 {
200 	if (Undefined(sec) || (Validate() != AUDIO_SUCCESS))
201 		return (AUDIO_UNKNOWN_SIZE);
202 
203 	// Round down to sample frame boundary
204 	return ((unsigned long) (AUDIO_MINFLOAT +
205 	    (((double)sec * (double)sample_rate) / (double)samples_per_unit)));
206 }
207 
208 // Return the number of bytes in a sample frame for the audio encoding.
209 unsigned int AudioHdr::
FrameLength() const210 FrameLength() const
211 {
212 	return (bytes_per_unit * channels);
213 }
214