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