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