1 /*
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
26 package javax.sound.sampled;
27
28 import java.util.Collections;
29 import java.util.HashMap;
30 import java.util.Map;
31
32 /**
33 * <code>AudioFormat</code> is the class that specifies a particular arrangement of data in a sound stream.
34 * By examing the information stored in the audio format, you can discover how to interpret the bits in the
35 * binary sound data.
36 * <p>
37 * Every data line has an audio format associated with its data stream. The audio format of a source (playback) data line indicates
38 * what kind of data the data line expects to receive for output. For a target (capture) data line, the audio format specifies the kind
39 * of the data that can be read from the line.
40 * Sound files also have audio formats, of course. The <code>{@link AudioFileFormat}</code>
41 * class encapsulates an <code>AudioFormat</code> in addition to other,
42 * file-specific information. Similarly, an <code>{@link AudioInputStream}</code> has an
43 * <code>AudioFormat</code>.
44 * <p>
45 * The <code>AudioFormat</code> class accommodates a number of common sound-file encoding techniques, including
46 * pulse-code modulation (PCM), mu-law encoding, and a-law encoding. These encoding techniques are predefined,
47 * but service providers can create new encoding types.
48 * The encoding that a specific format uses is named by its <code>encoding</code> field.
49 *<p>
50 * In addition to the encoding, the audio format includes other properties that further specify the exact
51 * arrangement of the data.
52 * These include the number of channels, sample rate, sample size, byte order, frame rate, and frame size.
53 * Sounds may have different numbers of audio channels: one for mono, two for stereo.
54 * The sample rate measures how many "snapshots" (samples) of the sound pressure are taken per second, per channel.
55 * (If the sound is stereo rather than mono, two samples are actually measured at each instant of time: one for the left channel,
56 * and another for the right channel; however, the sample rate still measures the number per channel, so the rate is the same
57 * regardless of the number of channels. This is the standard use of the term.)
58 * The sample size indicates how many bits are used to store each snapshot; 8 and 16 are typical values.
59 * For 16-bit samples (or any other sample size larger than a byte),
60 * byte order is important; the bytes in each sample are arranged in
61 * either the "little-endian" or "big-endian" style.
62 * For encodings like PCM, a frame consists of the set of samples for all channels at a given
63 * point in time, and so the size of a frame (in bytes) is always equal to the size of a sample (in bytes) times
64 * the number of channels. However, with some other sorts of encodings a frame can contain
65 * a bundle of compressed data for a whole series of samples, as well as additional, non-sample
66 * data. For such encodings, the sample rate and sample size refer to the data after it is decoded into PCM,
67 * and so they are completely different from the frame rate and frame size.
68 *
69 * <p>An <code>AudioFormat</code> object can include a set of
70 * properties. A property is a pair of key and value: the key
71 * is of type <code>String</code>, the associated property
72 * value is an arbitrary object. Properties specify
73 * additional format specifications, like the bit rate for
74 * compressed formats. Properties are mainly used as a means
75 * to transport additional information of the audio format
76 * to and from the service providers. Therefore, properties
77 * are ignored in the {@link #matches(AudioFormat)} method.
78 * However, methods which rely on the installed service
79 * providers, like {@link AudioSystem#isConversionSupported
80 * (AudioFormat, AudioFormat) isConversionSupported} may consider
81 * properties, depending on the respective service provider
82 * implementation.
83 *
84 * <p>The following table lists some common properties which
85 * service providers should use, if applicable:
86 *
87 * <table border=0>
88 * <tr>
89 * <th>Property key</th>
90 * <th>Value type</th>
91 * <th>Description</th>
92 * </tr>
93 * <tr>
94 * <td>"bitrate"</td>
95 * <td>{@link java.lang.Integer Integer}</td>
96 * <td>average bit rate in bits per second</td>
97 * </tr>
98 * <tr>
99 * <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 * @see DataLine#getFormat
119 * @see AudioInputStream#getFormat
120 * @see AudioFileFormat
121 * @see javax.sound.sampled.spi.FormatConversionProvider
122 * @since 1.3
123 */
124 public class AudioFormat {
125
126 // INSTANCE VARIABLES
127
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
165 /** The set of properties */
166 private HashMap<String, Object> properties;
167
168
169 /**
170 * Constructs an <code>AudioFormat</code> with the given parameters.
171 * The encoding specifies the convention used to represent the data.
172 * The other parameters are further explained in the {@link AudioFormat
173 * class description}.
174 * @param encoding the audio encoding technique
175 * @param sampleRate the number of samples per second
176 * @param sampleSizeInBits the number of bits in each sample
177 * @param channels the number of channels (1 for mono, 2 for stereo, and so on)
178 * @param frameSize the number of bytes in each frame
179 * @param frameRate the number of frames per second
180 * @param bigEndian indicates whether the data for a single sample
181 * is stored in big-endian byte order (<code>false</code>
182 * means little-endian)
183 */
184 public AudioFormat(Encoding encoding, float sampleRate, int sampleSizeInBits,
185 int channels, int frameSize, float frameRate, boolean bigEndian) {
186
187 this.encoding = encoding;
188 this.sampleRate = sampleRate;
189 this.sampleSizeInBits = sampleSizeInBits;
190 this.channels = channels;
191 this.frameSize = frameSize;
192 this.frameRate = frameRate;
193 this.bigEndian = bigEndian;
194 this.properties = null;
195 }
196
197
198 /**
199 * Constructs an <code>AudioFormat</code> with the given parameters.
200 * The encoding specifies the convention used to represent the data.
201 * The other parameters are further explained in the {@link AudioFormat
202 * class description}.
203 * @param encoding the audio encoding technique
204 * @param sampleRate the number of samples per second
205 * @param sampleSizeInBits the number of bits in each sample
206 * @param channels the number of channels (1 for mono, 2 for
207 * stereo, and so on)
208 * @param frameSize the number of bytes in each frame
209 * @param frameRate the number of frames per second
210 * @param bigEndian indicates whether the data for a single sample
211 * is stored in big-endian byte order
212 * (<code>false</code> means little-endian)
213 * @param properties a <code>Map<String,Object></code> object
214 * containing format properties
215 *
216 * @since 1.5
217 */
218 public AudioFormat(Encoding encoding, float sampleRate,
219 int sampleSizeInBits, int channels,
220 int frameSize, float frameRate,
221 boolean bigEndian, Map<String, Object> properties) {
222 this(encoding, sampleRate, sampleSizeInBits, channels,
223 frameSize, frameRate, bigEndian);
224 this.properties = new HashMap<String, Object>(properties);
225 }
226
227
228 /**
229 * Constructs an <code>AudioFormat</code> with a linear PCM encoding and
230 * the given parameters. The frame size is set to the number of bytes
231 * required to contain one sample from each channel, and the frame rate
232 * is set to the sample rate.
233 *
234 * @param sampleRate the number of samples per second
235 * @param sampleSizeInBits the number of bits in each sample
236 * @param channels the number of channels (1 for mono, 2 for stereo, and so on)
237 * @param signed indicates whether the data is signed or unsigned
238 * @param bigEndian indicates whether the data for a single sample
239 * is stored in big-endian byte order (<code>false</code>
240 * means little-endian)
241 */
242 public AudioFormat(float sampleRate, int sampleSizeInBits,
243 int channels, boolean signed, boolean bigEndian) {
244
245 this((signed == true ? Encoding.PCM_SIGNED : Encoding.PCM_UNSIGNED),
246 sampleRate,
247 sampleSizeInBits,
248 channels,
249 (channels == AudioSystem.NOT_SPECIFIED || sampleSizeInBits == AudioSystem.NOT_SPECIFIED)?
250 AudioSystem.NOT_SPECIFIED:
251 ((sampleSizeInBits + 7) / 8) * channels,
252 sampleRate,
253 bigEndian);
254 }
255
256 /**
257 * Obtains the type of encoding for sounds in this format.
258 *
259 * @return the encoding type
260 * @see Encoding#PCM_SIGNED
261 * @see Encoding#PCM_UNSIGNED
262 * @see Encoding#ULAW
263 * @see Encoding#ALAW
264 */
265 public Encoding getEncoding() {
266
267 return encoding;
268 }
269
270 /**
271 * Obtains the sample rate.
272 * For compressed formats, the return value is the sample rate of the uncompressed
273 * audio data.
274 * When this AudioFormat is used for queries (e.g. {@link
275 * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
276 * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
277 * DataLine.Info#getFormats() DataLine.Info.getFormats}), a sample rate of
278 * <code>AudioSystem.NOT_SPECIFIED</code> means that any sample rate is
279 * acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
280 * the sample rate is not defined for this audio format.
281 * @return the number of samples per second,
282 * or <code>AudioSystem.NOT_SPECIFIED</code>
283 *
284 * @see #getFrameRate()
285 * @see AudioSystem#NOT_SPECIFIED
286 */
287 public float getSampleRate() {
288
289 return sampleRate;
290 }
291
292 /**
293 * Obtains the size of a sample.
294 * For compressed formats, the return value is the sample size of the
295 * uncompressed audio data.
296 * When this AudioFormat is used for queries (e.g. {@link
297 * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
298 * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
299 * DataLine.Info#getFormats() DataLine.Info.getFormats}), a sample size of
300 * <code>AudioSystem.NOT_SPECIFIED</code> means that any sample size is
301 * acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
302 * the sample size is not defined for this audio format.
303 * @return the number of bits in each sample,
304 * or <code>AudioSystem.NOT_SPECIFIED</code>
305 *
306 * @see #getFrameSize()
307 * @see AudioSystem#NOT_SPECIFIED
308 */
309 public int getSampleSizeInBits() {
310
311 return sampleSizeInBits;
312 }
313
314 /**
315 * Obtains the number of channels.
316 * When this AudioFormat is used for queries (e.g. {@link
317 * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
318 * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
319 * DataLine.Info#getFormats() DataLine.Info.getFormats}), a return value of
320 * <code>AudioSystem.NOT_SPECIFIED</code> means that any (positive) number of channels is
321 * acceptable.
322 * @return The number of channels (1 for mono, 2 for stereo, etc.),
323 * or <code>AudioSystem.NOT_SPECIFIED</code>
324 *
325 * @see AudioSystem#NOT_SPECIFIED
326 */
327 public int getChannels() {
328
329 return channels;
330 }
331
332 /**
333 * Obtains the frame size in bytes.
334 * When this AudioFormat is used for queries (e.g. {@link
335 * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
336 * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
337 * DataLine.Info#getFormats() DataLine.Info.getFormats}), a frame size of
338 * <code>AudioSystem.NOT_SPECIFIED</code> means that any frame size is
339 * acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
340 * the frame size is not defined for this audio format.
341 * @return the number of bytes per frame,
342 * or <code>AudioSystem.NOT_SPECIFIED</code>
343 *
344 * @see #getSampleSizeInBits()
345 * @see AudioSystem#NOT_SPECIFIED
346 */
347 public int getFrameSize() {
348
349 return frameSize;
350 }
351
352 /**
353 * Obtains the frame rate in frames per second.
354 * When this AudioFormat is used for queries (e.g. {@link
355 * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
356 * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
357 * DataLine.Info#getFormats() DataLine.Info.getFormats}), a frame rate of
358 * <code>AudioSystem.NOT_SPECIFIED</code> means that any frame rate is
359 * acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
360 * the frame rate is not defined for this audio format.
361 * @return the number of frames per second,
362 * or <code>AudioSystem.NOT_SPECIFIED</code>
363 *
364 * @see #getSampleRate()
365 * @see AudioSystem#NOT_SPECIFIED
366 */
367 public float getFrameRate() {
368
369 return frameRate;
370 }
371
372
373 /**
374 * Indicates whether the audio data is stored in big-endian or little-endian
375 * byte order. If the sample size is not more than one byte, the return value is
376 * irrelevant.
377 * @return <code>true</code> if the data is stored in big-endian byte order,
378 * <code>false</code> if little-endian
379 */
380 public boolean isBigEndian() {
381
382 return bigEndian;
383 }
384
385
386 /**
387 * Obtain an unmodifiable map of properties.
388 * The concept of properties is further explained in
389 * the {@link AudioFileFormat class description}.
390 *
391 * @return a <code>Map<String,Object></code> object containing
392 * all properties. If no properties are recognized, an empty map is
393 * returned.
394 *
395 * @see #getProperty(String)
396 * @since 1.5
397 */
398 public Map<String,Object> properties() {
399 Map<String,Object> ret;
400 if (properties == null) {
401 ret = new HashMap<String,Object>(0);
402 } else {
403 ret = (Map<String,Object>) (properties.clone());
404 }
405 return (Map<String,Object>) Collections.unmodifiableMap(ret);
406 }
407
408
409 /**
410 * Obtain the property value specified by the key.
411 * The concept of properties is further explained in
412 * the {@link AudioFileFormat class description}.
413 *
414 * <p>If the specified property is not defined for a
415 * particular file format, this method returns
416 * <code>null</code>.
417 *
418 * @param key the key of the desired property
419 * @return the value of the property with the specified key,
420 * or <code>null</code> if the property does not exist.
421 *
422 * @see #properties()
423 * @since 1.5
424 */
425 public Object getProperty(String key) {
426 if (properties == null) {
427 return null;
428 }
429 return properties.get(key);
430 }
431
432
433 /**
434 * Indicates whether this format matches the one specified. To match,
435 * two formats must have the same encoding, the same number of channels,
436 * and the same number of bits per sample and bytes per frame.
437 * The two formats must also have the same sample rate,
438 * unless the specified format has the sample rate value <code>AudioSystem.NOT_SPECIFIED</code>,
439 * which any sample rate will match. The frame rates must
440 * similarly be equal, unless the specified format has the frame rate
441 * value <code>AudioSystem.NOT_SPECIFIED</code>. The byte order (big-endian or little-endian)
442 * must match if the sample size is greater than one byte.
443 *
444 * @param format format to test for match
445 * @return <code>true</code> if this format matches the one specified,
446 * <code>false</code> otherwise.
447 */
448 /*
449 * $$kk: 04.20.99: i changed the semantics of this.
450 */
451 public boolean matches(AudioFormat format) {
452
453 if (format.getEncoding().equals(getEncoding()) &&
454 ( (format.getSampleRate() == (float)AudioSystem.NOT_SPECIFIED) || (format.getSampleRate() == getSampleRate()) ) &&
455 (format.getSampleSizeInBits() == getSampleSizeInBits()) &&
456 (format.getChannels() == getChannels() &&
457 (format.getFrameSize() == getFrameSize()) &&
458 ( (format.getFrameRate() == (float)AudioSystem.NOT_SPECIFIED) || (format.getFrameRate() == getFrameRate()) ) &&
459 ( (format.getSampleSizeInBits() <= 8) || (format.isBigEndian() == isBigEndian()) ) ) )
460 return true;
461
462 return false;
463 }
464
465
466 /**
467 * Returns a string that describes the format, such as:
468 * "PCM SIGNED 22050 Hz 16 bit mono big-endian". The contents of the string
469 * may vary between implementations of Java Sound.
470 *
471 * @return a string that describes the format parameters
472 */
473 public String toString() {
474 String sEncoding = "";
475 if (getEncoding() != null) {
476 sEncoding = getEncoding().toString() + " ";
477 }
478
479 String sSampleRate;
480 if (getSampleRate() == (float) AudioSystem.NOT_SPECIFIED) {
481 sSampleRate = "unknown sample rate, ";
482 } else {
483 sSampleRate = "" + getSampleRate() + " Hz, ";
484 }
485
486 String sSampleSizeInBits;
487 if (getSampleSizeInBits() == (float) AudioSystem.NOT_SPECIFIED) {
488 sSampleSizeInBits = "unknown bits per sample, ";
489 } else {
490 sSampleSizeInBits = "" + getSampleSizeInBits() + " bit, ";
491 }
492
493 String sChannels;
494 if (getChannels() == 1) {
495 sChannels = "mono, ";
496 } else
497 if (getChannels() == 2) {
498 sChannels = "stereo, ";
499 } else {
500 if (getChannels() == AudioSystem.NOT_SPECIFIED) {
501 sChannels = " unknown number of channels, ";
502 } else {
503 sChannels = ""+getChannels()+" channels, ";
504 }
505 }
506
507 String sFrameSize;
508 if (getFrameSize() == (float) AudioSystem.NOT_SPECIFIED) {
509 sFrameSize = "unknown frame size, ";
510 } else {
511 sFrameSize = "" + getFrameSize()+ " bytes/frame, ";
512 }
513
514 String sFrameRate = "";
515 if (Math.abs(getSampleRate() - getFrameRate()) > 0.00001) {
516 if (getFrameRate() == (float) AudioSystem.NOT_SPECIFIED) {
517 sFrameRate = "unknown frame rate, ";
518 } else {
519 sFrameRate = getFrameRate() + " frames/second, ";
520 }
521 }
522
523 String sEndian = "";
524 if ((getEncoding().equals(Encoding.PCM_SIGNED)
525 || getEncoding().equals(Encoding.PCM_UNSIGNED))
526 && ((getSampleSizeInBits() > 8)
527 || (getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED))) {
528 if (isBigEndian()) {
529 sEndian = "big-endian";
530 } else {
531 sEndian = "little-endian";
532 }
533 }
534
535 return sEncoding
536 + sSampleRate
537 + sSampleSizeInBits
538 + sChannels
539 + sFrameSize
540 + sFrameRate
541 + sEndian;
542
543 }
544
545 /**
546 * The <code>Encoding</code> class names the specific type of data representation
547 * used for an audio stream. The encoding includes aspects of the
548 * sound format other than the number of channels, sample rate, sample size,
549 * frame rate, frame size, and byte order.
550 * <p>
551 * One ubiquitous type of audio encoding is pulse-code modulation (PCM),
552 * which is simply a linear (proportional) representation of the sound
553 * waveform. With PCM, the number stored in each sample is proportional
554 * to the instantaneous amplitude of the sound pressure at that point in
555 * time. The numbers are frequently signed or unsigned integers.
556 * Besides PCM, other encodings include mu-law and a-law, which are nonlinear
557 * mappings of the sound amplitude that are often used for recording speech.
558 * <p>
559 * You can use a predefined encoding by referring to one of the static
560 * objects created by this class, such as PCM_SIGNED or
561 * PCM_UNSIGNED. Service providers can create new encodings, such as
562 * compressed audio formats or floating-point PCM samples, and make
563 * these available through the <code>{@link AudioSystem}</code> class.
564 * <p>
565 * The <code>Encoding</code> class is static, so that all
566 * <code>AudioFormat</code> objects that have the same encoding will refer
567 * to the same object (rather than different instances of the same class).
568 * This allows matches to be made by checking that two format's encodings
569 * are equal.
570 *
571 * @see AudioFormat
572 * @see javax.sound.sampled.spi.FormatConversionProvider
573 *
574 * @author Kara Kytle
575 * @since 1.3
576 */
577 public static class Encoding {
578
579
580 // ENCODING DEFINES
581
582 /**
583 * Specifies signed, linear PCM data.
584 */
585 public static final Encoding PCM_SIGNED = new Encoding("PCM_SIGNED");
586
587 /**
588 * Specifies unsigned, linear PCM data.
589 */
590 public static final Encoding PCM_UNSIGNED = new Encoding("PCM_UNSIGNED");
591
592 /**
593 * Specifies u-law encoded data.
594 */
595 public static final Encoding ULAW = new Encoding("ULAW");
596
597 /**
598 * Specifies a-law encoded data.
599 */
600 public static final Encoding ALAW = new Encoding("ALAW");
601
602
603 // INSTANCE VARIABLES
604
605 /**
606 * Encoding name.
607 */
608 private String name;
609
610
611 // CONSTRUCTOR
612
613 /**
614 * Constructs a new encoding.
615 * @param name the name of the new type of encoding
616 */
617 public Encoding(String name) {
618 this.name = name;
619 }
620
621
622 // METHODS
623
624 /**
625 * Finalizes the equals method
626 */
627 public final boolean equals(Object obj) {
628 if (toString() == null) {
629 return (obj != null) && (obj.toString() == null);
630 }
631 if (obj instanceof Encoding) {
632 return toString().equals(obj.toString());
633 }
634 return false;
635 }
636
637 /**
638 * Finalizes the hashCode method
639 */
640 public final int hashCode() {
641 if (toString() == null) {
642 return 0;
643 }
644 return toString().hashCode();
645 }
646
647 /**
648 * Provides the <code>String</code> representation of the encoding. This <code>String</code> is
649 * the same name that was passed to the constructor. For the predefined encodings, the name
650 * is similar to the encoding's variable (field) name. For example, <code>PCM_SIGNED.toString()</code> returns
651 * the name "pcm_signed".
652 *
653 * @return the encoding name
654 */
655 public final String toString() {
656 return name;
657 }
658
659 } // class Encoding
660 }