blob: 6b4b6da9a4217a9194f7dca6d691355dad6abd08 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.media.sound;
27
28import javax.sound.sampled.AudioFormat;
29import javax.sound.sampled.AudioInputStream;
30import javax.sound.sampled.AudioSystem;
31
32/**
33 * Common conversions etc.
34 *
35 * @author Kara Kytle
36 * @author Florian Bomers
37 */
38public class Toolkit {
39
40
41 /**
42 * Converts bytes from signed to unsigned.
43 */
44 static void getUnsigned8(byte[] b, int off, int len) {
45 for (int i = off; i < (off+len); i++) {
46 b[i] += 128;
47 }
48 }
49
50
51 /**
52 * Swaps bytes.
53 * @throws ArrayOutOfBoundsException if len is not a multiple of 2.
54 */
55 static void getByteSwapped(byte[] b, int off, int len) {
56
57 byte tempByte;
58 for (int i = off; i < (off+len); i+=2) {
59
60 tempByte = b[i];
61 b[i] = b[i+1];
62 b[i+1] = tempByte;
63 }
64 }
65
66
67 /**
68 * Linear to DB scale conversion.
69 */
70 static float linearToDB(float linear) {
71
72 float dB = (float) (Math.log((double)((linear==0.0)?0.0001:linear))/Math.log(10.0) * 20.0);
73 return dB;
74 }
75
76
77 /**
78 * DB to linear scale conversion.
79 */
80 static float dBToLinear(float dB) {
81
82 float linear = (float) Math.pow(10.0, dB/20.0);
83 return linear;
84 }
85
86 /*
87 * returns bytes aligned to a multiple of blocksize
88 * the return value will be in the range of (bytes-blocksize+1) ... bytes
89 */
90 static long align(long bytes, int blockSize) {
91 // prevent null pointers
92 if (blockSize <= 1) {
93 return bytes;
94 }
95 return bytes - (bytes % blockSize);
96 }
97
98 static int align(int bytes, int blockSize) {
99 // prevent null pointers
100 if (blockSize <= 1) {
101 return bytes;
102 }
103 return bytes - (bytes % blockSize);
104 }
105
106
107 /*
108 * gets the number of bytes needed to play the specified number of milliseconds
109 */
110 static long millis2bytes(AudioFormat format, long millis) {
111 long result = (long) (millis * format.getFrameRate() / 1000.0f * format.getFrameSize());
112 return align(result, format.getFrameSize());
113 }
114
115 /*
116 * gets the time in milliseconds for the given number of bytes
117 */
118 static long bytes2millis(AudioFormat format, long bytes) {
119 return (long) (bytes / format.getFrameRate() * 1000.0f / format.getFrameSize());
120 }
121
122 /*
123 * gets the number of bytes needed to play the specified number of microseconds
124 */
125 static long micros2bytes(AudioFormat format, long micros) {
126 long result = (long) (micros * format.getFrameRate() / 1000000.0f * format.getFrameSize());
127 return align(result, format.getFrameSize());
128 }
129
130 /*
131 * gets the time in microseconds for the given number of bytes
132 */
133 static long bytes2micros(AudioFormat format, long bytes) {
134 return (long) (bytes / format.getFrameRate() * 1000000.0f / format.getFrameSize());
135 }
136
137 /*
138 * gets the number of frames needed to play the specified number of microseconds
139 */
140 static long micros2frames(AudioFormat format, long micros) {
141 return (long) (micros * format.getFrameRate() / 1000000.0f);
142 }
143
144 /*
145 * gets the time in microseconds for the given number of frames
146 */
147 static long frames2micros(AudioFormat format, long frames) {
148 return (long) (((double) frames) / format.getFrameRate() * 1000000.0d);
149 }
150
151 static void isFullySpecifiedAudioFormat(AudioFormat format) {
152 if (!format.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)
153 && !format.getEncoding().equals(AudioFormat.Encoding.PCM_UNSIGNED)
154 && !format.getEncoding().equals(AudioFormat.Encoding.ULAW)
155 && !format.getEncoding().equals(AudioFormat.Encoding.ALAW)) {
156 // we don't know how to verify possibly non-linear encodings
157 return;
158 }
159 if (format.getFrameRate() <= 0) {
160 throw new IllegalArgumentException("invalid frame rate: "
161 +((format.getFrameRate()==-1)?
162 "NOT_SPECIFIED":String.valueOf(format.getFrameRate())));
163 }
164 if (format.getSampleRate() <= 0) {
165 throw new IllegalArgumentException("invalid sample rate: "
166 +((format.getSampleRate()==-1)?
167 "NOT_SPECIFIED":String.valueOf(format.getSampleRate())));
168 }
169 if (format.getSampleSizeInBits() <= 0) {
170 throw new IllegalArgumentException("invalid sample size in bits: "
171 +((format.getSampleSizeInBits()==-1)?
172 "NOT_SPECIFIED":String.valueOf(format.getSampleSizeInBits())));
173 }
174 if (format.getFrameSize() <= 0) {
175 throw new IllegalArgumentException("invalid frame size: "
176 +((format.getFrameSize()==-1)?
177 "NOT_SPECIFIED":String.valueOf(format.getFrameSize())));
178 }
179 if (format.getChannels() <= 0) {
180 throw new IllegalArgumentException("invalid number of channels: "
181 +((format.getChannels()==-1)?
182 "NOT_SPECIFIED":String.valueOf(format.getChannels())));
183 }
184 }
185
186
187 static boolean isFullySpecifiedPCMFormat(AudioFormat format) {
188 if (!format.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)
189 && !format.getEncoding().equals(AudioFormat.Encoding.PCM_UNSIGNED)) {
190 return false;
191 }
192 if ((format.getFrameRate() <= 0)
193 || (format.getSampleRate() <= 0)
194 || (format.getSampleSizeInBits() <= 0)
195 || (format.getFrameSize() <= 0)
196 || (format.getChannels() <= 0)) {
197 return false;
198 }
199 return true;
200 }
201
202
203 public static AudioInputStream getPCMConvertedAudioInputStream(AudioInputStream ais) {
204 // we can't open the device for non-PCM playback, so we have
205 // convert any other encodings to PCM here (at least we try!)
206 AudioFormat af = ais.getFormat();
207
208 if( (!af.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)) &&
209 (!af.getEncoding().equals(AudioFormat.Encoding.PCM_UNSIGNED))) {
210
211 try {
212 AudioFormat newFormat =
213 new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
214 af.getSampleRate(),
215 16,
216 af.getChannels(),
217 af.getChannels() * 2,
218 af.getSampleRate(),
219 Platform.isBigEndian());
220 ais = AudioSystem.getAudioInputStream(newFormat, ais);
221 } catch (Exception e) {
222 if (Printer.err) e.printStackTrace();
223 ais = null;
224 }
225 }
226
227 return ais;
228 }
229
230}