1 /* 2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * 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. 435 * To match, two formats must have the same encoding, 436 * and consistent values of the number of channels, sample rate, sample size, 437 * frame rate, and frame size. 438 * The values of the property are consistent if they are equal 439 * or the specified format has the property value 440 * {@code AudioSystem.NOT_SPECIFIED}. 441 * The byte order (big-endian or little-endian) must be the same 442 * if the sample size is greater than one byte. 443 * 444 * @param format format to test for match 445 * @return {@code true} if this format matches the one specified, 446 * {@code false} otherwise. 447 */ 448 public boolean matches(AudioFormat format) { 449 if (format.getEncoding().equals(getEncoding()) 450 && (format.getChannels() == AudioSystem.NOT_SPECIFIED 451 || format.getChannels() == getChannels()) 452 && (format.getSampleRate() == (float)AudioSystem.NOT_SPECIFIED 453 || format.getSampleRate() == getSampleRate()) 454 && (format.getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED 455 || format.getSampleSizeInBits() == getSampleSizeInBits()) 456 && (format.getFrameRate() == (float)AudioSystem.NOT_SPECIFIED 457 || format.getFrameRate() == getFrameRate()) 458 && (format.getFrameSize() == AudioSystem.NOT_SPECIFIED 459 || format.getFrameSize() == getFrameSize()) 460 && (getSampleSizeInBits() <= 8 461 || format.isBigEndian() == isBigEndian())) { 462 return true; 463 } 464 return false; 465 } 466 467 468 /** 469 * Returns a string that describes the format, such as: 470 * "PCM SIGNED 22050 Hz 16 bit mono big-endian". The contents of the string 471 * may vary between implementations of Java Sound. 472 * 473 * @return a string that describes the format parameters 474 */ 475 public String toString() { 476 String sEncoding = ""; 477 if (getEncoding() != null) { 478 sEncoding = getEncoding().toString() + " "; 479 } 480 481 String sSampleRate; 482 if (getSampleRate() == (float) AudioSystem.NOT_SPECIFIED) { 483 sSampleRate = "unknown sample rate, "; 484 } else { 485 sSampleRate = "" + getSampleRate() + " Hz, "; 486 } 487 488 String sSampleSizeInBits; 489 if (getSampleSizeInBits() == (float) AudioSystem.NOT_SPECIFIED) { 490 sSampleSizeInBits = "unknown bits per sample, "; 491 } else { 492 sSampleSizeInBits = "" + getSampleSizeInBits() + " bit, "; 493 } 494 495 String sChannels; 496 if (getChannels() == 1) { 497 sChannels = "mono, "; 498 } else 499 if (getChannels() == 2) { 500 sChannels = "stereo, "; 501 } else { 502 if (getChannels() == AudioSystem.NOT_SPECIFIED) { 503 sChannels = " unknown number of channels, "; 504 } else { 505 sChannels = ""+getChannels()+" channels, "; 506 } 507 } 508 509 String sFrameSize; 510 if (getFrameSize() == (float) AudioSystem.NOT_SPECIFIED) { 511 sFrameSize = "unknown frame size, "; 512 } else { 513 sFrameSize = "" + getFrameSize()+ " bytes/frame, "; 514 } 515 516 String sFrameRate = ""; 517 if (Math.abs(getSampleRate() - getFrameRate()) > 0.00001) { 518 if (getFrameRate() == (float) AudioSystem.NOT_SPECIFIED) { 519 sFrameRate = "unknown frame rate, "; 520 } else { 521 sFrameRate = getFrameRate() + " frames/second, "; 522 } 523 } 524 525 String sEndian = ""; 526 if ((getEncoding().equals(Encoding.PCM_SIGNED) 527 || getEncoding().equals(Encoding.PCM_UNSIGNED)) 528 && ((getSampleSizeInBits() > 8) 529 || (getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED))) { 530 if (isBigEndian()) { 531 sEndian = "big-endian"; 532 } else { 533 sEndian = "little-endian"; 534 } 535 } 536 537 return sEncoding 538 + sSampleRate 539 + sSampleSizeInBits 540 + sChannels 541 + sFrameSize 542 + sFrameRate 543 + sEndian; 544 545 } 546 547 /** 548 * The <code>Encoding</code> class names the specific type of data representation 549 * used for an audio stream. The encoding includes aspects of the 550 * sound format other than the number of channels, sample rate, sample size, 551 * frame rate, frame size, and byte order. 552 * <p> 553 * One ubiquitous type of audio encoding is pulse-code modulation (PCM), 554 * which is simply a linear (proportional) representation of the sound 555 * waveform. With PCM, the number stored in each sample is proportional 556 * to the instantaneous amplitude of the sound pressure at that point in 557 * time. The numbers may be signed or unsigned integers or floats. 558 * Besides PCM, other encodings include mu-law and a-law, which are nonlinear 559 * mappings of the sound amplitude that are often used for recording speech. 560 * <p> 561 * You can use a predefined encoding by referring to one of the static 562 * objects created by this class, such as PCM_SIGNED or 563 * PCM_UNSIGNED. Service providers can create new encodings, such as 564 * compressed audio formats, and make 565 * these available through the <code>{@link AudioSystem}</code> class. 566 * <p> 567 * The <code>Encoding</code> class is static, so that all 568 * <code>AudioFormat</code> objects that have the same encoding will refer 569 * to the same object (rather than different instances of the same class). 570 * This allows matches to be made by checking that two format's encodings 571 * are equal. 572 * 573 * @see AudioFormat 574 * @see javax.sound.sampled.spi.FormatConversionProvider 575 * 576 * @author Kara Kytle 577 * @since 1.3 578 */ 579 public static class Encoding { 580 581 582 // ENCODING DEFINES 583 584 /** 585 * Specifies signed, linear PCM data. 586 */ 587 public static final Encoding PCM_SIGNED = new Encoding("PCM_SIGNED"); 588 589 /** 590 * Specifies unsigned, linear PCM data. 591 */ 592 public static final Encoding PCM_UNSIGNED = new Encoding("PCM_UNSIGNED"); 593 594 /** 595 * Specifies floating-point PCM data. 596 * 597 * @since 1.7 598 */ 599 public static final Encoding PCM_FLOAT = new Encoding("PCM_FLOAT"); 600 601 /** 602 * Specifies u-law encoded data. 603 */ 604 public static final Encoding ULAW = new Encoding("ULAW"); 605 606 /** 607 * Specifies a-law encoded data. 608 */ 609 public static final Encoding ALAW = new Encoding("ALAW"); 610 611 612 // INSTANCE VARIABLES 613 614 /** 615 * Encoding name. 616 */ 617 private String name; 618 619 620 // CONSTRUCTOR 621 622 /** 623 * Constructs a new encoding. 624 * @param name the name of the new type of encoding 625 */ 626 public Encoding(String name) { 627 this.name = name; 628 } 629 630 631 // METHODS 632 633 /** 634 * Finalizes the equals method 635 */ 636 public final boolean equals(Object obj) { 637 if (toString() == null) { 638 return (obj != null) && (obj.toString() == null); 639 } 640 if (obj instanceof Encoding) { 641 return toString().equals(obj.toString()); 642 } 643 return false; 644 } 645 646 /** 647 * Finalizes the hashCode method 648 */ 649 public final int hashCode() { 650 if (toString() == null) { 651 return 0; 652 } 653 return toString().hashCode(); 654 } 655 656 /** 657 * Provides the <code>String</code> representation of the encoding. This <code>String</code> is 658 * the same name that was passed to the constructor. For the predefined encodings, the name 659 * is similar to the encoding's variable (field) name. For example, <code>PCM_SIGNED.toString()</code> returns 660 * the name "pcm_signed". 661 * 662 * @return the encoding name 663 */ 664 public final String toString() { 665 return name; 666 } 667 668 } // class Encoding 669 }