Path: blob/master/src/java.desktop/share/classes/javax/sound/sampled/AudioFormat.java
41159 views
/*1* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.sound.sampled;2627import java.util.Collections;28import java.util.HashMap;29import java.util.Map;30import java.util.Objects;3132/**33* {@code AudioFormat} is the class that specifies a particular arrangement of34* data in a sound stream. By examining the information stored in the audio35* 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. The38* audio format of a source (playback) data line indicates what kind of data the39* 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 the41* line.42* <p>43* Sound files also have audio formats, of course. The {@link AudioFileFormat}44* class encapsulates an {@code AudioFormat} in addition to other, file-specific45* information. Similarly, an {@link AudioInputStream} has an46* {@code AudioFormat}.47* <p>48* The {@code AudioFormat} class accommodates a number of common sound-file49* encoding techniques, including pulse-code modulation (PCM), mu-law encoding,50* and a-law encoding. These encoding techniques are predefined, but service51* providers can create new encoding types. The encoding that a specific format52* uses is named by its {@code encoding} field.53* <p>54* In addition to the encoding, the audio format includes other properties that55* further specify the exact arrangement of the data. These include the number56* of channels, sample rate, sample size, byte order, frame rate, and frame57* size. Sounds may have different numbers of audio channels: one for mono, two58* for stereo. The sample rate measures how many "snapshots" (samples) of the59* sound pressure are taken per second, per channel. (If the sound is stereo60* rather than mono, two samples are actually measured at each instant of time:61* one for the left channel, and another for the right channel; however, the62* sample rate still measures the number per channel, so the rate is the same63* regardless of the number of channels. This is the standard use of the term.)64* The sample size indicates how many bits are used to store each snapshot; 865* and 16 are typical values. For 16-bit samples (or any other sample size66* larger than a byte), byte order is important; the bytes in each sample are67* arranged in either the "little-endian" or "big-endian" style. For encodings68* like PCM, a frame consists of the set of samples for all channels at a given69* point in time, and so the size of a frame (in bytes) is always equal to the70* size of a sample (in bytes) times the number of channels. However, with some71* other sorts of encodings a frame can contain a bundle of compressed data for72* a whole series of samples, as well as additional, non-sample data. For such73* encodings, the sample rate and sample size refer to the data after it is74* decoded into PCM, and so they are completely different from the frame rate75* and frame size.76* <p>77* An {@code AudioFormat} object can include a set of properties. A property is78* a pair of key and value: the key is of type {@code String}, the associated79* property value is an arbitrary object. Properties specify additional format80* specifications, like the bit rate for compressed formats. Properties are81* mainly used as a means to transport additional information of the audio82* format to and from the service providers. Therefore, properties are ignored83* in the {@link #matches(AudioFormat)} method. However, methods which rely on84* the installed service providers, like85* {@link AudioSystem#isConversionSupported (AudioFormat, AudioFormat)86* isConversionSupported} may consider properties, depending on the respective87* service provider implementation.88* <p>89* The following table lists some common properties which service providers90* should use, if applicable:91*92* <table class="striped">93* <caption>Audio Format Properties</caption>94* <thead>95* <tr>96* <th scope="col">Property key97* <th scope="col">Value type98* <th scope="col">Description99* </thead>100* <tbody>101* <tr>102* <th scope="row">"bitrate"103* <td>{@link java.lang.Integer Integer}104* <td>average bit rate in bits per second105* <tr>106* <th scope="row">"vbr"107* <td>{@link java.lang.Boolean Boolean}108* <td>{@code true}, if the file is encoded in variable bit rate (VBR)109* <tr>110* <th scope="row">"quality"111* <td>{@link java.lang.Integer Integer}112* <td>encoding/conversion quality, 1..100113* </tbody>114* </table>115* <p>116* Vendors of service providers (plugins) are encouraged to seek information117* about other already established properties in third party plugins, and follow118* the same conventions.119*120* @author Kara Kytle121* @author Florian Bomers122* @see DataLine#getFormat123* @see AudioInputStream#getFormat124* @see AudioFileFormat125* @see javax.sound.sampled.spi.FormatConversionProvider126* @since 1.3127*/128public class AudioFormat {129130/**131* The audio encoding technique used by this format.132*/133protected Encoding encoding;134135/**136* The number of samples played or recorded per second, for sounds that have137* this format.138*/139protected float sampleRate;140141/**142* The number of bits in each sample of a sound that has this format.143*/144protected int sampleSizeInBits;145146/**147* The number of audio channels in this format (1 for mono, 2 for stereo).148*/149protected int channels;150151/**152* The number of bytes in each frame of a sound that has this format.153*/154protected int frameSize;155156/**157* The number of frames played or recorded per second, for sounds that have158* this format.159*/160protected float frameRate;161162/**163* Indicates whether the audio data is stored in big-endian or little-endian164* order.165*/166protected boolean bigEndian;167168/**169* The set of properties.170*/171private HashMap<String, Object> properties;172173/**174* Constructs an {@code AudioFormat} with the given parameters. The encoding175* specifies the convention used to represent the data. The other parameters176* are further explained in the {@link AudioFormat class description}.177*178* @param encoding the audio encoding technique179* @param sampleRate the number of samples per second180* @param sampleSizeInBits the number of bits in each sample181* @param channels the number of channels (1 for mono, 2 for stereo, and so182* on)183* @param frameSize the number of bytes in each frame184* @param frameRate the number of frames per second185* @param bigEndian indicates whether the data for a single sample is186* stored in big-endian byte order ({@code false} means187* little-endian)188*/189public AudioFormat(Encoding encoding, float sampleRate, int sampleSizeInBits,190int channels, int frameSize, float frameRate, boolean bigEndian) {191192this.encoding = encoding;193this.sampleRate = sampleRate;194this.sampleSizeInBits = sampleSizeInBits;195this.channels = channels;196this.frameSize = frameSize;197this.frameRate = frameRate;198this.bigEndian = bigEndian;199this.properties = null;200}201202/**203* Constructs an {@code AudioFormat} with the given parameters. The encoding204* specifies the convention used to represent the data. The other parameters205* are further explained in the {@link AudioFormat class description}.206*207* @param encoding the audio encoding technique208* @param sampleRate the number of samples per second209* @param sampleSizeInBits the number of bits in each sample210* @param channels the number of channels (1 for mono, 2 for stereo, and so211* on)212* @param frameSize the number of bytes in each frame213* @param frameRate the number of frames per second214* @param bigEndian indicates whether the data for a single sample is215* stored in big-endian byte order ({@code false} means216* little-endian)217* @param properties a {@code Map<String, Object>} object containing format218* properties219* @since 1.5220*/221public AudioFormat(Encoding encoding, float sampleRate,222int sampleSizeInBits, int channels,223int frameSize, float frameRate,224boolean bigEndian, Map<String, Object> properties) {225this(encoding, sampleRate, sampleSizeInBits, channels,226frameSize, frameRate, bigEndian);227this.properties = new HashMap<>(properties);228}229230/**231* Constructs an {@code AudioFormat} with a linear PCM encoding and the232* given parameters. The frame size is set to the number of bytes required233* to contain one sample from each channel, and the frame rate is set to the234* sample rate.235*236* @param sampleRate the number of samples per second237* @param sampleSizeInBits the number of bits in each sample238* @param channels the number of channels (1 for mono, 2 for stereo, and so239* on)240* @param signed indicates whether the data is signed or unsigned241* @param bigEndian indicates whether the data for a single sample is242* stored in big-endian byte order ({@code false} means243* little-endian)244*/245public AudioFormat(float sampleRate, int sampleSizeInBits,246int channels, boolean signed, boolean bigEndian) {247248this((signed == true ? Encoding.PCM_SIGNED : Encoding.PCM_UNSIGNED),249sampleRate,250sampleSizeInBits,251channels,252(channels == AudioSystem.NOT_SPECIFIED || sampleSizeInBits == AudioSystem.NOT_SPECIFIED)?253AudioSystem.NOT_SPECIFIED:254((sampleSizeInBits + 7) / 8) * channels,255sampleRate,256bigEndian);257}258259/**260* Obtains the type of encoding for sounds in this format.261*262* @return the encoding type263* @see Encoding#PCM_SIGNED264* @see Encoding#PCM_UNSIGNED265* @see Encoding#ULAW266* @see Encoding#ALAW267*/268public Encoding getEncoding() {269return encoding;270}271272/**273* Obtains the sample rate. For compressed formats, the return value is the274* sample rate of the uncompressed audio data. When this {@code AudioFormat}275* is used for queries (e.g.276* {@link AudioSystem#isConversionSupported(AudioFormat, AudioFormat)277* AudioSystem.isConversionSupported}) or capabilities (e.g.278* {@link DataLine.Info#getFormats DataLine.Info.getFormats}), a sample rate279* of {@code AudioSystem.NOT_SPECIFIED} means that any sample rate is280* acceptable. {@code AudioSystem.NOT_SPECIFIED} is also returned when the281* sample rate is not defined for this audio format.282*283* @return the number of samples per second, or284* {@code AudioSystem.NOT_SPECIFIED}285* @see #getFrameRate()286* @see AudioSystem#NOT_SPECIFIED287*/288public float getSampleRate() {289return sampleRate;290}291292/**293* Obtains the size of a sample. For compressed formats, the return value is294* the sample size of the uncompressed audio data. When this295* {@code AudioFormat} is used for queries (e.g.296* {@link AudioSystem#isConversionSupported(AudioFormat,AudioFormat)297* AudioSystem.isConversionSupported}) or capabilities (e.g.298* {@link DataLine.Info#getFormats DataLine.Info.getFormats}), a sample size299* of {@code AudioSystem.NOT_SPECIFIED} means that any sample size is300* acceptable. {@code AudioSystem.NOT_SPECIFIED} is also returned when the301* sample size is not defined for this audio format.302*303* @return the number of bits in each sample, or304* {@code AudioSystem.NOT_SPECIFIED}305* @see #getFrameSize()306* @see AudioSystem#NOT_SPECIFIED307*/308public int getSampleSizeInBits() {309return sampleSizeInBits;310}311312/**313* Obtains the number of channels. When this {@code AudioFormat} is used for314* queries (e.g. {@link AudioSystem#isConversionSupported(AudioFormat,315* AudioFormat) AudioSystem.isConversionSupported}) or capabilities (e.g.316* {@link DataLine.Info#getFormats DataLine.Info.getFormats}), a return317* value of {@code AudioSystem.NOT_SPECIFIED} means that any (positive)318* number of channels is acceptable.319*320* @return The number of channels (1 for mono, 2 for stereo, etc.), or321* {@code AudioSystem.NOT_SPECIFIED}322* @see AudioSystem#NOT_SPECIFIED323*/324public int getChannels() {325return channels;326}327328/**329* Obtains the frame size in bytes. When this {@code AudioFormat} is used330* for queries (e.g. {@link AudioSystem#isConversionSupported(AudioFormat,331* AudioFormat) AudioSystem.isConversionSupported}) or capabilities (e.g.332* {@link DataLine.Info#getFormats DataLine.Info.getFormats}), a frame size333* of {@code AudioSystem.NOT_SPECIFIED} means that any frame size is334* acceptable. {@code AudioSystem.NOT_SPECIFIED} is also returned when the335* frame size is not defined for this audio format.336*337* @return the number of bytes per frame, or338* {@code AudioSystem.NOT_SPECIFIED}339* @see #getSampleSizeInBits()340* @see AudioSystem#NOT_SPECIFIED341*/342public int getFrameSize() {343return frameSize;344}345346/**347* Obtains the frame rate in frames per second. When this348* {@code AudioFormat} is used for queries (e.g.349* {@link AudioSystem#isConversionSupported(AudioFormat,AudioFormat)350* AudioSystem.isConversionSupported}) or capabilities (e.g.351* {@link DataLine.Info#getFormats DataLine.Info.getFormats}), a frame rate352* of {@code AudioSystem.NOT_SPECIFIED} means that any frame rate is353* acceptable. {@code AudioSystem.NOT_SPECIFIED} is also returned when the354* frame rate is not defined for this audio format.355*356* @return the number of frames per second, or357* {@code AudioSystem.NOT_SPECIFIED}358* @see #getSampleRate()359* @see AudioSystem#NOT_SPECIFIED360*/361public float getFrameRate() {362return frameRate;363}364365/**366* Indicates whether the audio data is stored in big-endian or little-endian367* byte order. If the sample size is not more than one byte, the return368* value is irrelevant.369*370* @return {@code true} if the data is stored in big-endian byte order,371* {@code false} if little-endian372*/373public boolean isBigEndian() {374return bigEndian;375}376377/**378* Obtain an unmodifiable map of properties. The concept of properties is379* further explained in the {@link AudioFileFormat class description}.380*381* @return a {@code Map<String, Object>} object containing all properties.382* If no properties are recognized, an empty map is returned.383* @see #getProperty(String)384* @since 1.5385*/386@SuppressWarnings("unchecked") // Cast of result of clone.387public Map<String,Object> properties() {388Map<String,Object> ret;389if (properties == null) {390ret = new HashMap<>(0);391} else {392ret = (Map<String,Object>) (properties.clone());393}394return Collections.unmodifiableMap(ret);395}396397/**398* Obtain the property value specified by the key. The concept of properties399* is further explained in the {@link AudioFileFormat class description}.400* <p>401* If the specified property is not defined for a particular file format,402* this method returns {@code null}.403*404* @param key the key of the desired property405* @return the value of the property with the specified key, or {@code null}406* if the property does not exist407* @see #properties()408* @since 1.5409*/410public Object getProperty(String key) {411if (properties == null) {412return null;413}414return properties.get(key);415}416417/**418* Indicates whether this format matches the one specified. To match, two419* formats must have the same encoding, and consistent values of the number420* of channels, sample rate, sample size, frame rate, and frame size. The421* values of the property are consistent if they are equal or the specified422* format has the property value {@code AudioSystem.NOT_SPECIFIED}. The byte423* order (big-endian or little-endian) must be the same if the sample size424* is greater than one byte.425*426* @param format format to test for match427* @return {@code true} if this format matches the one specified,428* {@code false} otherwise429*/430public boolean matches(AudioFormat format) {431if (format.getEncoding().equals(getEncoding())432&& (format.getChannels() == AudioSystem.NOT_SPECIFIED433|| format.getChannels() == getChannels())434&& (format.getSampleRate() == (float)AudioSystem.NOT_SPECIFIED435|| format.getSampleRate() == getSampleRate())436&& (format.getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED437|| format.getSampleSizeInBits() == getSampleSizeInBits())438&& (format.getFrameRate() == (float)AudioSystem.NOT_SPECIFIED439|| format.getFrameRate() == getFrameRate())440&& (format.getFrameSize() == AudioSystem.NOT_SPECIFIED441|| format.getFrameSize() == getFrameSize())442&& (getSampleSizeInBits() <= 8443|| format.isBigEndian() == isBigEndian())) {444return true;445}446return false;447}448449/**450* Returns a string that describes the audio format, such as: "PCM SIGNED451* 22050 Hz 16 bit mono big-endian". The contents of the string may vary452* between implementations of Java Sound.453*454* @return a string representation of the audio format455*/456@Override457public String toString() {458String sampleRate = getSampleRate() == AudioSystem.NOT_SPECIFIED ?459"unknown sample rate" : getSampleRate() + " Hz";460461String sampleSize = getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED ?462"unknown bits per sample" : getSampleSizeInBits() + " bit";463464String channels = switch (getChannels()) {465case 1 -> "mono";466case 2 -> "stereo";467case AudioSystem.NOT_SPECIFIED -> "unknown number of channels";468default -> getChannels() + " channels";469};470471String frameSize = getFrameSize() == AudioSystem.NOT_SPECIFIED ?472"unknown frame size" : getFrameSize() + " bytes/frame";473474String frameRate = "";475if (Math.abs(getSampleRate() - getFrameRate()) > 0.00001) {476frameRate = getFrameRate() == AudioSystem.NOT_SPECIFIED ?477", unknown frame rate":", " + getFrameRate() + " frames/second";478}479480String bigEndian = "";481if ((getEncoding().equals(Encoding.PCM_SIGNED)482|| getEncoding().equals(Encoding.PCM_UNSIGNED))483&& ((getSampleSizeInBits() > 8)484|| (getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED))) {485bigEndian = isBigEndian() ? ", big-endian" : ", little-endian";486}487488return String.format("%s %s, %s, %s, %s%s%s", getEncoding(),489sampleRate, sampleSize, channels, frameSize,490frameRate, bigEndian);491}492493/**494* The {@code Encoding} class names the specific type of data representation495* used for an audio stream. The encoding includes aspects of the sound496* format other than the number of channels, sample rate, sample size, frame497* rate, frame size, and byte order.498* <p>499* One ubiquitous type of audio encoding is pulse-code modulation (PCM),500* which is simply a linear (proportional) representation of the sound501* waveform. With PCM, the number stored in each sample is proportional to502* the instantaneous amplitude of the sound pressure at that point in time.503* The numbers may be signed or unsigned integers or floats. Besides PCM,504* other encodings include mu-law and a-law, which are nonlinear mappings of505* the sound amplitude that are often used for recording speech.506* <p>507* You can use a predefined encoding by referring to one of the static508* objects created by this class, such as {@code PCM_SIGNED} or509* {@code PCM_UNSIGNED}. Service providers can create new encodings, such as510* compressed audio formats, and make these available through the511* {@link AudioSystem} class.512* <p>513* The {@code Encoding} class is static, so that all {@code AudioFormat}514* objects that have the same encoding will refer to the same object (rather515* than different instances of the same class). This allows matches to be516* made by checking that two format's encodings are equal.517*518* @author Kara Kytle519* @see AudioFormat520* @see javax.sound.sampled.spi.FormatConversionProvider521* @since 1.3522*/523public static class Encoding {524525/**526* Specifies signed, linear PCM data.527*/528public static final Encoding PCM_SIGNED = new Encoding("PCM_SIGNED");529530/**531* Specifies unsigned, linear PCM data.532*/533public static final Encoding PCM_UNSIGNED = new Encoding("PCM_UNSIGNED");534535/**536* Specifies floating-point PCM data.537*538* @since 1.7539*/540public static final Encoding PCM_FLOAT = new Encoding("PCM_FLOAT");541542/**543* Specifies u-law encoded data.544*/545public static final Encoding ULAW = new Encoding("ULAW");546547/**548* Specifies a-law encoded data.549*/550public static final Encoding ALAW = new Encoding("ALAW");551552/**553* Encoding name.554*/555private final String name;556557/**558* Constructs a new encoding.559*560* @param name the name of the new type of encoding561*/562public Encoding(final String name) {563this.name = name;564}565566/**567* Indicates whether the specified object is equal to this encoding,568* returning {@code true} if the objects are equal.569*570* @param obj the reference object with which to compare571* @return {@code true} if the specified object is equal to this572* encoding; {@code false} otherwise573*/574@Override575public final boolean equals(final Object obj) {576if (this == obj) {577return true;578}579if (!(obj instanceof Encoding)) {580return false;581}582return Objects.equals(name, ((Encoding) obj).name);583}584585/**586* Returns a hash code value for this encoding.587*588* @return a hash code value for this encoding589*/590@Override591public final int hashCode() {592return name != null ? name.hashCode() : 0;593}594595/**596* Returns encoding's name as the string representation of the encoding.597* For the predefined encodings, the name is similar to the encoding's598* variable (field) name. For example, {@code PCM_SIGNED.toString()}599* returns the name "PCM_SIGNED".600*601* @return a string representation of the encoding602*/603@Override604public final String toString() {605return name;606}607}608}609610611