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