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