001 /*
002 * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.sound.sampled;
027
028 import java.util.Collections;
029 import java.util.HashMap;
030 import java.util.Map;
031
032 /**
033 * <code>AudioFormat</code> is the class that specifies a particular arrangement of data in a sound stream.
034 * By examing the information stored in the audio format, you can discover how to interpret the bits in the
035 * binary sound data.
036 * <p>
037 * Every data line has an audio format associated with its data stream. The audio format of a source (playback) data line indicates
038 * what kind of data the data line expects to receive for output. For a target (capture) data line, the audio format specifies the kind
039 * of the data that can be read from the line.
040 * Sound files also have audio formats, of course. The <code>{@link AudioFileFormat}</code>
041 * class encapsulates an <code>AudioFormat</code> in addition to other,
042 * file-specific information. Similarly, an <code>{@link AudioInputStream}</code> has an
043 * <code>AudioFormat</code>.
044 * <p>
045 * The <code>AudioFormat</code> class accommodates a number of common sound-file encoding techniques, including
046 * pulse-code modulation (PCM), mu-law encoding, and a-law encoding. These encoding techniques are predefined,
047 * but service providers can create new encoding types.
048 * The encoding that a specific format uses is named by its <code>encoding</code> field.
049 *<p>
050 * In addition to the encoding, the audio format includes other properties that further specify the exact
051 * arrangement of the data.
052 * These include the number of channels, sample rate, sample size, byte order, frame rate, and frame size.
053 * Sounds may have different numbers of audio channels: one for mono, two for stereo.
054 * The sample rate measures how many "snapshots" (samples) of the sound pressure are taken per second, per channel.
055 * (If the sound is stereo rather than mono, two samples are actually measured at each instant of time: one for the left channel,
056 * and another for the right channel; however, the sample rate still measures the number per channel, so the rate is the same
057 * regardless of the number of channels. This is the standard use of the term.)
058 * The sample size indicates how many bits are used to store each snapshot; 8 and 16 are typical values.
059 * For 16-bit samples (or any other sample size larger than a byte),
060 * byte order is important; the bytes in each sample are arranged in
061 * either the "little-endian" or "big-endian" style.
062 * For encodings like PCM, a frame consists of the set of samples for all channels at a given
063 * point in time, and so the size of a frame (in bytes) is always equal to the size of a sample (in bytes) times
064 * the number of channels. However, with some other sorts of encodings a frame can contain
065 * a bundle of compressed data for a whole series of samples, as well as additional, non-sample
066 * data. For such encodings, the sample rate and sample size refer to the data after it is decoded into PCM,
067 * and so they are completely different from the frame rate and frame size.
068 *
069 * <p>An <code>AudioFormat</code> object can include a set of
070 * properties. A property is a pair of key and value: the key
071 * is of type <code>String</code>, the associated property
072 * value is an arbitrary object. Properties specify
073 * additional format specifications, like the bit rate for
074 * compressed formats. Properties are mainly used as a means
075 * to transport additional information of the audio format
076 * to and from the service providers. Therefore, properties
077 * are ignored in the {@link #matches(AudioFormat)} method.
078 * However, methods which rely on the installed service
079 * providers, like {@link AudioSystem#isConversionSupported
080 * (AudioFormat, AudioFormat) isConversionSupported} may consider
081 * properties, depending on the respective service provider
082 * implementation.
083 *
084 * <p>The following table lists some common properties which
085 * service providers should use, if applicable:
086 *
087 * <table border=0>
088 * <tr>
089 * <th>Property key</th>
090 * <th>Value type</th>
091 * <th>Description</th>
092 * </tr>
093 * <tr>
094 * <td>"bitrate"</td>
095 * <td>{@link java.lang.Integer Integer}</td>
096 * <td>average bit rate in bits per second</td>
097 * </tr>
098 * <tr>
099 * <td>"vbr"</td>
100 * <td>{@link java.lang.Boolean Boolean}</td>
101 * <td><code>true</code>, if the file is encoded in variable bit
102 * rate (VBR)</td>
103 * </tr>
104 * <tr>
105 * <td>"quality"</td>
106 * <td>{@link java.lang.Integer Integer}</td>
107 * <td>encoding/conversion quality, 1..100</td>
108 * </tr>
109 * </table>
110 *
111 * <p>Vendors of service providers (plugins) are encouraged
112 * to seek information about other already established
113 * properties in third party plugins, and follow the same
114 * conventions.
115 *
116 * @author Kara Kytle
117 * @author Florian Bomers
118 * @version 1.41 07/05/05
119 * @see DataLine#getFormat
120 * @see AudioInputStream#getFormat
121 * @see AudioFileFormat
122 * @see javax.sound.sampled.spi.FormatConversionProvider
123 * @since 1.3
124 */
125 public class AudioFormat {
126
127 // INSTANCE VARIABLES
128
129 /**
130 * The audio encoding technique used by this format.
131 */
132 protected Encoding encoding;
133
134 /**
135 * The number of samples played or recorded per second, for sounds that have this format.
136 */
137 protected float sampleRate;
138
139 /**
140 * The number of bits in each sample of a sound that has this format.
141 */
142 protected int sampleSizeInBits;
143
144 /**
145 * The number of audio channels in this format (1 for mono, 2 for stereo).
146 */
147 protected int channels;
148
149 /**
150 * The number of bytes in each frame of a sound that has this format.
151 */
152 protected int frameSize;
153
154 /**
155 * The number of frames played or recorded per second, for sounds that have this format.
156 */
157 protected float frameRate;
158
159 /**
160 * Indicates whether the audio data is stored in big-endian or little-endian order.
161 */
162 protected boolean bigEndian;
163
164 /** The set of properties */
165 private HashMap<String, Object> properties;
166
167 /**
168 * Constructs an <code>AudioFormat</code> with the given parameters.
169 * The encoding specifies the convention used to represent the data.
170 * The other parameters are further explained in the {@link AudioFormat
171 * class description}.
172 * @param encoding the audio encoding technique
173 * @param sampleRate the number of samples per second
174 * @param sampleSizeInBits the number of bits in each sample
175 * @param channels the number of channels (1 for mono, 2 for stereo, and so on)
176 * @param frameSize the number of bytes in each frame
177 * @param frameRate the number of frames per second
178 * @param bigEndian indicates whether the data for a single sample
179 * is stored in big-endian byte order (<code>false</code>
180 * means little-endian)
181 */
182 public AudioFormat(Encoding encoding, float sampleRate,
183 int sampleSizeInBits, int channels, int frameSize,
184 float frameRate, boolean bigEndian) {
185
186 this .encoding = encoding;
187 this .sampleRate = sampleRate;
188 this .sampleSizeInBits = sampleSizeInBits;
189 this .channels = channels;
190 this .frameSize = frameSize;
191 this .frameRate = frameRate;
192 this .bigEndian = bigEndian;
193 this .properties = null;
194 }
195
196 /**
197 * Constructs an <code>AudioFormat</code> with the given parameters.
198 * The encoding specifies the convention used to represent the data.
199 * The other parameters are further explained in the {@link AudioFormat
200 * class description}.
201 * @param encoding the audio encoding technique
202 * @param sampleRate the number of samples per second
203 * @param sampleSizeInBits the number of bits in each sample
204 * @param channels the number of channels (1 for mono, 2 for
205 * stereo, and so on)
206 * @param frameSize the number of bytes in each frame
207 * @param frameRate the number of frames per second
208 * @param bigEndian indicates whether the data for a single sample
209 * is stored in big-endian byte order
210 * (<code>false</code> means little-endian)
211 * @param properties a <code>Map<String,Object></code> object
212 * containing format properties
213 *
214 * @since 1.5
215 */
216 public AudioFormat(Encoding encoding, float sampleRate,
217 int sampleSizeInBits, int channels, int frameSize,
218 float frameRate, boolean bigEndian,
219 Map<String, Object> properties) {
220 this (encoding, sampleRate, sampleSizeInBits, channels,
221 frameSize, frameRate, bigEndian);
222 this .properties = new HashMap<String, Object>(properties);
223 }
224
225 /**
226 * Constructs an <code>AudioFormat</code> with a linear PCM encoding and
227 * the given parameters. The frame size is set to the number of bytes
228 * required to contain one sample from each channel, and the frame rate
229 * is set to the sample rate.
230 *
231 * @param sampleRate the number of samples per second
232 * @param sampleSizeInBits the number of bits in each sample
233 * @param channels the number of channels (1 for mono, 2 for stereo, and so on)
234 * @param signed indicates whether the data is signed or unsigned
235 * @param bigEndian indicates whether the data for a single sample
236 * is stored in big-endian byte order (<code>false</code>
237 * means little-endian)
238 */
239 public AudioFormat(float sampleRate, int sampleSizeInBits,
240 int channels, boolean signed, boolean bigEndian) {
241
242 this (
243 (signed == true ? Encoding.PCM_SIGNED
244 : Encoding.PCM_UNSIGNED),
245 sampleRate,
246 sampleSizeInBits,
247 channels,
248 (channels == AudioSystem.NOT_SPECIFIED || sampleSizeInBits == AudioSystem.NOT_SPECIFIED) ? AudioSystem.NOT_SPECIFIED
249 : ((sampleSizeInBits + 7) / 8) * channels,
250 sampleRate, bigEndian);
251 }
252
253 /**
254 * Obtains the type of encoding for sounds in this format.
255 *
256 * @return the encoding type
257 * @see Encoding#PCM_SIGNED
258 * @see Encoding#PCM_UNSIGNED
259 * @see Encoding#ULAW
260 * @see Encoding#ALAW
261 */
262 public Encoding getEncoding() {
263
264 return encoding;
265 }
266
267 /**
268 * Obtains the sample rate.
269 * For compressed formats, the return value is the sample rate of the uncompressed
270 * audio data.
271 * When this AudioFormat is used for queries (e.g. {@link
272 * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
273 * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
274 * DataLine.Info#getFormats() DataLine.Info.getFormats}), a sample rate of
275 * <code>AudioSystem.NOT_SPECIFIED</code> means that any sample rate is
276 * acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
277 * the sample rate is not defined for this audio format.
278 * @return the number of samples per second,
279 * or <code>AudioSystem.NOT_SPECIFIED</code>
280 *
281 * @see #getFrameRate()
282 * @see AudioSystem#NOT_SPECIFIED
283 */
284 public float getSampleRate() {
285
286 return sampleRate;
287 }
288
289 /**
290 * Obtains the size of a sample.
291 * For compressed formats, the return value is the sample size of the
292 * uncompressed audio data.
293 * When this AudioFormat is used for queries (e.g. {@link
294 * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
295 * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
296 * DataLine.Info#getFormats() DataLine.Info.getFormats}), a sample size of
297 * <code>AudioSystem.NOT_SPECIFIED</code> means that any sample size is
298 * acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
299 * the sample size is not defined for this audio format.
300 * @return the number of bits in each sample,
301 * or <code>AudioSystem.NOT_SPECIFIED</code>
302 *
303 * @see #getFrameSize()
304 * @see AudioSystem#NOT_SPECIFIED
305 */
306 public int getSampleSizeInBits() {
307
308 return sampleSizeInBits;
309 }
310
311 /**
312 * Obtains the number of channels.
313 * When this AudioFormat is used for queries (e.g. {@link
314 * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
315 * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
316 * DataLine.Info#getFormats() DataLine.Info.getFormats}), a return value of
317 * <code>AudioSystem.NOT_SPECIFIED</code> means that any (positive) number of channels is
318 * acceptable.
319 * @return The number of channels (1 for mono, 2 for stereo, etc.),
320 * or <code>AudioSystem.NOT_SPECIFIED</code>
321 *
322 * @see AudioSystem#NOT_SPECIFIED
323 */
324 public int getChannels() {
325
326 return channels;
327 }
328
329 /**
330 * Obtains the frame size in bytes.
331 * When this AudioFormat is used for queries (e.g. {@link
332 * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
333 * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
334 * DataLine.Info#getFormats() DataLine.Info.getFormats}), a frame size of
335 * <code>AudioSystem.NOT_SPECIFIED</code> means that any frame size is
336 * acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
337 * the frame size is not defined for this audio format.
338 * @return the number of bytes per frame,
339 * or <code>AudioSystem.NOT_SPECIFIED</code>
340 *
341 * @see #getSampleSizeInBits()
342 * @see AudioSystem#NOT_SPECIFIED
343 */
344 public int getFrameSize() {
345
346 return frameSize;
347 }
348
349 /**
350 * Obtains the frame rate in frames per second.
351 * When this AudioFormat is used for queries (e.g. {@link
352 * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
353 * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
354 * DataLine.Info#getFormats() DataLine.Info.getFormats}), a frame rate of
355 * <code>AudioSystem.NOT_SPECIFIED</code> means that any frame rate is
356 * acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
357 * the frame rate is not defined for this audio format.
358 * @return the number of frames per second,
359 * or <code>AudioSystem.NOT_SPECIFIED</code>
360 *
361 * @see #getSampleRate()
362 * @see AudioSystem#NOT_SPECIFIED
363 */
364 public float getFrameRate() {
365
366 return frameRate;
367 }
368
369 /**
370 * Indicates whether the audio data is stored in big-endian or little-endian
371 * byte order. If the sample size is not more than one byte, the return value is
372 * irrelevant.
373 * @return <code>true</code> if the data is stored in big-endian byte order,
374 * <code>false</code> if little-endian
375 */
376 public boolean isBigEndian() {
377
378 return bigEndian;
379 }
380
381 /**
382 * Obtain an unmodifiable map of properties.
383 * The concept of properties is further explained in
384 * the {@link AudioFileFormat class description}.
385 *
386 * @return a <code>Map<String,Object></code> object containing
387 * all properties. If no properties are recognized, an empty map is
388 * returned.
389 *
390 * @see #getProperty(String)
391 * @since 1.5
392 */
393 public Map<String, Object> properties() {
394 Map<String, Object> ret;
395 if (properties == null) {
396 ret = new HashMap<String, Object>(0);
397 } else {
398 ret = (Map<String, Object>) (properties.clone());
399 }
400 return (Map<String, Object>) Collections.unmodifiableMap(ret);
401 }
402
403 /**
404 * Obtain the property value specified by the key.
405 * The concept of properties is further explained in
406 * the {@link AudioFileFormat class description}.
407 *
408 * <p>If the specified property is not defined for a
409 * particular file format, this method returns
410 * <code>null</code>.
411 *
412 * @param key the key of the desired property
413 * @return the value of the property with the specified key,
414 * or <code>null</code> if the property does not exist.
415 *
416 * @see #properties()
417 * @since 1.5
418 */
419 public Object getProperty(String key) {
420 if (properties == null) {
421 return null;
422 }
423 return properties.get(key);
424 }
425
426 /**
427 * Indicates whether this format matches the one specified. To match,
428 * two formats must have the same encoding, the same number of channels,
429 * and the same number of bits per sample and bytes per frame.
430 * The two formats must also have the same sample rate,
431 * unless the specified format has the sample rate value <code>AudioSystem.NOT_SPECIFIED</code>,
432 * which any sample rate will match. The frame rates must
433 * similarly be equal, unless the specified format has the frame rate
434 * value <code>AudioSystem.NOT_SPECIFIED</code>. The byte order (big-endian or little-endian)
435 * must match if the sample size is greater than one byte.
436 *
437 * @param format format to test for match
438 * @return <code>true</code> if this format matches the one specified,
439 * <code>false</code> otherwise.
440 */
441 /*
442 * $$kk: 04.20.99: i changed the semantics of this.
443 */
444 public boolean matches(AudioFormat format) {
445
446 if (format.getEncoding().equals(getEncoding())
447 && ((format.getSampleRate() == (float) AudioSystem.NOT_SPECIFIED) || (format
448 .getSampleRate() == getSampleRate()))
449 && (format.getSampleSizeInBits() == getSampleSizeInBits())
450 && (format.getChannels() == getChannels()
451 && (format.getFrameSize() == getFrameSize())
452 && ((format.getFrameRate() == (float) AudioSystem.NOT_SPECIFIED) || (format
453 .getFrameRate() == getFrameRate())) && ((format
454 .getSampleSizeInBits() <= 8) || (format
455 .isBigEndian() == isBigEndian()))))
456 return true;
457
458 return false;
459 }
460
461 /**
462 * Returns a string that describes the format, such as:
463 * "PCM SIGNED 22050 Hz 16 bit mono big-endian". The contents of the string
464 * may vary between implementations of Java Sound.
465 *
466 * @return a string that describes the format parameters
467 */
468 public String toString() {
469 String sEncoding = "";
470 if (getEncoding() != null) {
471 sEncoding = getEncoding().toString() + " ";
472 }
473
474 String sSampleRate;
475 if (getSampleRate() == (float) AudioSystem.NOT_SPECIFIED) {
476 sSampleRate = "unknown sample rate, ";
477 } else {
478 sSampleRate = "" + getSampleRate() + " Hz, ";
479 }
480
481 String sSampleSizeInBits;
482 if (getSampleSizeInBits() == (float) AudioSystem.NOT_SPECIFIED) {
483 sSampleSizeInBits = "unknown bits per sample, ";
484 } else {
485 sSampleSizeInBits = "" + getSampleSizeInBits() + " bit, ";
486 }
487
488 String sChannels;
489 if (getChannels() == 1) {
490 sChannels = "mono, ";
491 } else if (getChannels() == 2) {
492 sChannels = "stereo, ";
493 } else {
494 if (getChannels() == AudioSystem.NOT_SPECIFIED) {
495 sChannels = " unknown number of channels, ";
496 } else {
497 sChannels = "" + getChannels() + " channels, ";
498 }
499 }
500
501 String sFrameSize;
502 if (getFrameSize() == (float) AudioSystem.NOT_SPECIFIED) {
503 sFrameSize = "unknown frame size, ";
504 } else {
505 sFrameSize = "" + getFrameSize() + " bytes/frame, ";
506 }
507
508 String sFrameRate = "";
509 if (Math.abs(getSampleRate() - getFrameRate()) > 0.00001) {
510 if (getFrameRate() == (float) AudioSystem.NOT_SPECIFIED) {
511 sFrameRate = "unknown frame rate, ";
512 } else {
513 sFrameRate = getFrameRate() + " frames/second, ";
514 }
515 }
516
517 String sEndian = "";
518 if ((getEncoding().equals(Encoding.PCM_SIGNED) || getEncoding()
519 .equals(Encoding.PCM_UNSIGNED))
520 && ((getSampleSizeInBits() > 8) || (getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED))) {
521 if (isBigEndian()) {
522 sEndian = "big-endian";
523 } else {
524 sEndian = "little-endian";
525 }
526 }
527
528 return sEncoding + sSampleRate + sSampleSizeInBits + sChannels
529 + sFrameSize + sFrameRate + sEndian;
530
531 }
532
533 /**
534 * The <code>Encoding</code> class names the specific type of data representation
535 * used for an audio stream. The encoding includes aspects of the
536 * sound format other than the number of channels, sample rate, sample size,
537 * frame rate, frame size, and byte order.
538 * <p>
539 * One ubiquitous type of audio encoding is pulse-code modulation (PCM),
540 * which is simply a linear (proportional) representation of the sound
541 * waveform. With PCM, the number stored in each sample is proportional
542 * to the instantaneous amplitude of the sound pressure at that point in
543 * time. The numbers are frequently signed or unsigned integers.
544 * Besides PCM, other encodings include mu-law and a-law, which are nonlinear
545 * mappings of the sound amplitude that are often used for recording speech.
546 * <p>
547 * You can use a predefined encoding by referring to one of the static
548 * objects created by this class, such as PCM_SIGNED or
549 * PCM_UNSIGNED. Service providers can create new encodings, such as
550 * compressed audio formats or floating-point PCM samples, and make
551 * these available through the <code>{@link AudioSystem}</code> class.
552 * <p>
553 * The <code>Encoding</code> class is static, so that all
554 * <code>AudioFormat</code> objects that have the same encoding will refer
555 * to the same object (rather than different instances of the same class).
556 * This allows matches to be made by checking that two format's encodings
557 * are equal.
558 *
559 * @see AudioFormat
560 * @see javax.sound.sampled.spi.FormatConversionProvider
561 *
562 * @author Kara Kytle
563 * @version 1.41 07/05/05
564 * @since 1.3
565 */
566 public static class Encoding {
567
568 // ENCODING DEFINES
569
570 /**
571 * Specifies signed, linear PCM data.
572 */
573 public static final Encoding PCM_SIGNED = new Encoding(
574 "PCM_SIGNED");
575
576 /**
577 * Specifies unsigned, linear PCM data.
578 */
579 public static final Encoding PCM_UNSIGNED = new Encoding(
580 "PCM_UNSIGNED");
581
582 /**
583 * Specifies u-law encoded data.
584 */
585 public static final Encoding ULAW = new Encoding("ULAW");
586
587 /**
588 * Specifies a-law encoded data.
589 */
590 public static final Encoding ALAW = new Encoding("ALAW");
591
592 // INSTANCE VARIABLES
593
594 /**
595 * Encoding name.
596 */
597 private String name;
598
599 // CONSTRUCTOR
600
601 /**
602 * Constructs a new encoding.
603 * @param name the name of the new type of encoding
604 */
605 public Encoding(String name) {
606 this .name = name;
607 }
608
609 // METHODS
610
611 /**
612 * Finalizes the equals method
613 */
614 public final boolean equals(Object obj) {
615 if (toString() == null) {
616 return (obj != null) && (obj.toString() == null);
617 }
618 if (obj instanceof Encoding) {
619 return toString().equals(obj.toString());
620 }
621 return false;
622 }
623
624 /**
625 * Finalizes the hashCode method
626 */
627 public final int hashCode() {
628 if (toString() == null) {
629 return 0;
630 }
631 return toString().hashCode();
632 }
633
634 /**
635 * Provides the <code>String</code> representation of the encoding. This <code>String</code> is
636 * the same name that was passed to the constructor. For the predefined encodings, the name
637 * is similar to the encoding's variable (field) name. For example, <code>PCM_SIGNED.toString()</code> returns
638 * the name "pcm_signed".
639 *
640 * @return the encoding name
641 */
642 public final String toString() {
643 return name;
644 }
645
646 } // class Encoding
647 }
|