KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > sound > sampled > AudioFormat


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
8 package javax.sound.sampled;
9
10 import java.util.Collections JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.Map JavaDoc;
13
14 /**
15  * <code>AudioFormat</code> is the class that specifies a particular arrangement of data in a sound stream.
16  * By examing the information stored in the audio format, you can discover how to interpret the bits in the
17  * binary sound data.
18  * <p>
19  * Every data line has an audio format associated with its data stream. The audio format of a source (playback) data line indicates
20  * what kind of data the data line expects to receive for output. For a target (capture) data line, the audio format specifies the kind
21  * of the data that can be read from the line.
22  * Sound files also have audio formats, of course. The <code>{@link AudioFileFormat}</code>
23  * class encapsulates an <code>AudioFormat</code> in addition to other,
24  * file-specific information. Similarly, an <code>{@link AudioInputStream}</code> has an
25  * <code>AudioFormat</code>.
26  * <p>
27  * The <code>AudioFormat</code> class accommodates a number of common sound-file encoding techniques, including
28  * pulse-code modulation (PCM), mu-law encoding, and a-law encoding. These encoding techniques are predefined,
29  * but service providers can create new encoding types.
30  * The encoding that a specific format uses is named by its <code>encoding</code> field.
31  *<p>
32  * In addition to the encoding, the audio format includes other properties that further specify the exact
33  * arrangement of the data.
34  * These include the number of channels, sample rate, sample size, byte order, frame rate, and frame size.
35  * Sounds may have different numbers of audio channels: one for mono, two for stereo.
36  * The sample rate measures how many "snapshots" (samples) of the sound pressure are taken per second, per channel.
37  * (If the sound is stereo rather than mono, two samples are actually measured at each instant of time: one for the left channel,
38  * and another for the right channel; however, the sample rate still measures the number per channel, so the rate is the same
39  * regardless of the number of channels. This is the standard use of the term.)
40  * The sample size indicates how many bits are used to store each snapshot; 8 and 16 are typical values.
41  * For 16-bit samples (or any other sample size larger than a byte),
42  * byte order is important; the bytes in each sample are arranged in
43  * either the "little-endian" or "big-endian" style.
44  * For encodings like PCM, a frame consists of the set of samples for all channels at a given
45  * point in time, and so the size of a frame (in bytes) is always equal to the size of a sample (in bytes) times
46  * the number of channels. However, with some other sorts of encodings a frame can contain
47  * a bundle of compressed data for a whole series of samples, as well as additional, non-sample
48  * data. For such encodings, the sample rate and sample size refer to the data after it is decoded into PCM,
49  * and so they are completely different from the frame rate and frame size.
50  *
51  * <p>An <code>AudioFormat</code> object can include a set of
52  * properties. A property is a pair of key and value: the key
53  * is of type <code>String</code>, the associated property
54  * value is an arbitrary object. Properties specify
55  * additional format specifications, like the bit rate for
56  * compressed formats. Properties are mainly used as a means
57  * to transport additional information of the audio format
58  * to and from the service providers. Therefore, properties
59  * are ignored in the {@link #matches(AudioFormat)} method.
60  * However, methods which rely on the installed service
61  * providers, like {@link AudioSystem#isConversionSupported
62  * (AudioFormat, AudioFormat) isConversionSupported} may consider
63  * properties, depending on the respective service provider
64  * implementation.
65  *
66  * <p>The following table lists some common properties which
67  * service providers should use, if applicable:
68  *
69  * <table border=0>
70  * <tr>
71  * <th>Property key</th>
72  * <th>Value type</th>
73  * <th>Description</th>
74  * </tr>
75  * <tr>
76  * <td>&quot;bitrate&quot;</td>
77  * <td>{@link java.lang.Integer Integer}</td>
78  * <td>average bit rate in bits per second</td>
79  * </tr>
80  * <tr>
81  * <td>&quot;vbr&quot;</td>
82  * <td>{@link java.lang.Boolean Boolean}</td>
83  * <td><code>true</code>, if the file is encoded in variable bit
84  * rate (VBR)</td>
85  * </tr>
86  * <tr>
87  * <td>&quot;quality&quot;</td>
88  * <td>{@link java.lang.Integer Integer}</td>
89  * <td>encoding/conversion quality, 1..100</td>
90  * </tr>
91  * </table>
92  *
93  * <p>Vendors of service providers (plugins) are encouraged
94  * to seek information about other already established
95  * properties in third party plugins, and follow the same
96  * conventions.
97  *
98  * @author Kara Kytle
99  * @author Florian Bomers
100  * @version 1.35 04/03/15
101  * @see DataLine#getFormat
102  * @see AudioInputStream#getFormat
103  * @see AudioFileFormat
104  * @see javax.sound.sampled.spi.FormatConversionProvider
105  * @since 1.3
106  */

107 public class AudioFormat {
108
109     // INSTANCE VARIABLES
110

111
112     /**
113      * The audio encoding technique used by this format.
114      */

115     protected Encoding encoding;
116
117     /**
118      * The number of samples played or recorded per second, for sounds that have this format.
119      */

120     protected float sampleRate;
121
122     /**
123      * The number of bits in each sample of a sound that has this format.
124      */

125     protected int sampleSizeInBits;
126
127     /**
128      * The number of audio channels in this format (1 for mono, 2 for stereo).
129      */

130     protected int channels;
131
132     /**
133      * The number of bytes in each frame of a sound that has this format.
134      */

135     protected int frameSize;
136
137     /**
138      * The number of frames played or recorded per second, for sounds that have this format.
139      */

140     protected float frameRate;
141
142     /**
143      * Indicates whether the audio data is stored in big-endian or little-endian order.
144      */

145     protected boolean bigEndian;
146
147
148     /** The set of properties */
149     private HashMap JavaDoc<String JavaDoc, Object JavaDoc> properties;
150
151
152     /**
153      * Constructs an <code>AudioFormat</code> with the given parameters.
154      * The encoding specifies the convention used to represent the data.
155      * The other parameters are further explained in the {@link AudioFormat
156      * class description}.
157      * @param encoding the audio encoding technique
158      * @param sampleRate the number of samples per second
159      * @param sampleSizeInBits the number of bits in each sample
160      * @param channels the number of channels (1 for mono, 2 for stereo, and so on)
161      * @param frameSize the number of bytes in each frame
162      * @param frameRate the number of frames per second
163      * @param bigEndian indicates whether the data for a single sample
164      * is stored in big-endian byte order (<code>false</code>
165      * means little-endian)
166      */

167     public AudioFormat(Encoding encoding, float sampleRate, int sampleSizeInBits,
168                int channels, int frameSize, float frameRate, boolean bigEndian) {
169
170     this.encoding = encoding;
171     this.sampleRate = sampleRate;
172     this.sampleSizeInBits = sampleSizeInBits;
173     this.channels = channels;
174     this.frameSize = frameSize;
175     this.frameRate = frameRate;
176     this.bigEndian = bigEndian;
177     this.properties = null;
178     }
179
180
181     /**
182      * Constructs an <code>AudioFormat</code> with the given parameters.
183      * The encoding specifies the convention used to represent the data.
184      * The other parameters are further explained in the {@link AudioFormat
185      * class description}.
186      * @param encoding the audio encoding technique
187      * @param sampleRate the number of samples per second
188      * @param sampleSizeInBits the number of bits in each sample
189      * @param channels the number of channels (1 for mono, 2 for
190      * stereo, and so on)
191      * @param frameSize the number of bytes in each frame
192      * @param frameRate the number of frames per second
193      * @param bigEndian indicates whether the data for a single sample
194      * is stored in big-endian byte order
195      * (<code>false</code> means little-endian)
196      * @param properties a <code>Map&lt;String,Object&gt;</code> object
197      * containing format properties
198      *
199      * @since 1.5
200      */

201     public AudioFormat(Encoding encoding, float sampleRate,
202                int sampleSizeInBits, int channels,
203                int frameSize, float frameRate,
204                boolean bigEndian, Map JavaDoc<String JavaDoc, Object JavaDoc> properties) {
205     this(encoding, sampleRate, sampleSizeInBits, channels,
206          frameSize, frameRate, bigEndian);
207     this.properties = new HashMap JavaDoc<String JavaDoc, Object JavaDoc>(properties);
208     }
209
210
211     /**
212      * Constructs an <code>AudioFormat</code> with a linear PCM encoding and
213      * the given parameters. The frame size is set to the number of bytes
214      * required to contain one sample from each channel, and the frame rate
215      * is set to the sample rate.
216      *
217      * @param sampleRate the number of samples per second
218      * @param sampleSizeInBits the number of bits in each sample
219      * @param channels the number of channels (1 for mono, 2 for stereo, and so on)
220      * @param signed indicates whether the data is signed or unsigned
221      * @param bigEndian indicates whether the data for a single sample
222      * is stored in big-endian byte order (<code>false</code>
223      * means little-endian)
224      */

225     public AudioFormat(float sampleRate, int sampleSizeInBits,
226                int channels, boolean signed, boolean bigEndian) {
227
228     this((signed == true ? Encoding.PCM_SIGNED : Encoding.PCM_UNSIGNED),
229          sampleRate,
230          sampleSizeInBits,
231          channels,
232          (channels == AudioSystem.NOT_SPECIFIED || sampleSizeInBits == AudioSystem.NOT_SPECIFIED)?
233          AudioSystem.NOT_SPECIFIED:
234          ((sampleSizeInBits + 7) / 8) * channels,
235          sampleRate,
236          bigEndian);
237     }
238
239     /**
240      * Obtains the type of encoding for sounds in this format.
241      *
242      * @return the encoding type
243      * @see Encoding#PCM_SIGNED
244      * @see Encoding#PCM_UNSIGNED
245      * @see Encoding#ULAW
246      * @see Encoding#ALAW
247      */

248     public Encoding getEncoding() {
249
250     return encoding;
251     }
252
253     /**
254      * Obtains the sample rate.
255      * For compressed formats, the return value is the sample rate of the uncompressed
256      * audio data.
257      * When this AudioFormat is used for queries (e.g. {@link
258      * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
259      * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
260      * DataLine.Info#getFormats() DataLine.Info.getFormats}), a sample rate of
261      * <code>AudioSystem.NOT_SPECIFIED</code> means that any sample rate is
262      * acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
263      * the sample rate is not defined for this audio format.
264      * @return the number of samples per second,
265      * or <code>AudioSystem.NOT_SPECIFIED</code>
266      *
267      * @see #getFrameRate()
268      * @see AudioSystem#NOT_SPECIFIED
269      */

270     public float getSampleRate() {
271
272     return sampleRate;
273     }
274
275     /**
276      * Obtains the size of a sample.
277      * For compressed formats, the return value is the sample size of the
278      * uncompressed audio data.
279      * When this AudioFormat is used for queries (e.g. {@link
280      * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
281      * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
282      * DataLine.Info#getFormats() DataLine.Info.getFormats}), a sample size of
283      * <code>AudioSystem.NOT_SPECIFIED</code> means that any sample size is
284      * acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
285      * the sample size is not defined for this audio format.
286      * @return the number of bits in each sample,
287      * or <code>AudioSystem.NOT_SPECIFIED</code>
288      *
289      * @see #getFrameSize()
290      * @see AudioSystem#NOT_SPECIFIED
291      */

292     public int getSampleSizeInBits() {
293
294     return sampleSizeInBits;
295     }
296
297     /**
298      * Obtains the number of channels.
299      * When this AudioFormat is used for queries (e.g. {@link
300      * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
301      * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
302      * DataLine.Info#getFormats() DataLine.Info.getFormats}), a return value of
303      * <code>AudioSystem.NOT_SPECIFIED</code> means that any (positive) number of channels is
304      * acceptable.
305      * @return The number of channels (1 for mono, 2 for stereo, etc.),
306      * or <code>AudioSystem.NOT_SPECIFIED</code>
307      *
308      * @see AudioSystem#NOT_SPECIFIED
309      */

310     public int getChannels() {
311
312     return channels;
313     }
314
315     /**
316      * Obtains the frame size in bytes.
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 frame size of
321      * <code>AudioSystem.NOT_SPECIFIED</code> means that any frame size is
322      * acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
323      * the frame size is not defined for this audio format.
324      * @return the number of bytes per frame,
325      * or <code>AudioSystem.NOT_SPECIFIED</code>
326      *
327      * @see #getSampleSizeInBits()
328      * @see AudioSystem#NOT_SPECIFIED
329      */

330     public int getFrameSize() {
331
332     return frameSize;
333     }
334
335     /**
336      * Obtains the frame rate in frames per second.
337      * When this AudioFormat is used for queries (e.g. {@link
338      * AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
339      * AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
340      * DataLine.Info#getFormats() DataLine.Info.getFormats}), a frame rate of
341      * <code>AudioSystem.NOT_SPECIFIED</code> means that any frame rate is
342      * acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
343      * the frame rate is not defined for this audio format.
344      * @return the number of frames per second,
345      * or <code>AudioSystem.NOT_SPECIFIED</code>
346      *
347      * @see #getSampleRate()
348      * @see AudioSystem#NOT_SPECIFIED
349      */

350     public float getFrameRate() {
351
352     return frameRate;
353     }
354
355
356     /**
357      * Indicates whether the audio data is stored in big-endian or little-endian
358      * byte order. If the sample size is not more than one byte, the return value is
359      * irrelevant.
360      * @return <code>true</code> if the data is stored in big-endian byte order,
361      * <code>false</code> if little-endian
362      */

363     public boolean isBigEndian() {
364
365     return bigEndian;
366     }
367
368
369     /**
370      * Obtain an unmodifiable map of properties.
371      * The concept of properties is further explained in
372      * the {@link AudioFileFormat class description}.
373      *
374      * @return a <code>Map&lt;String,Object&gt;</code> object containing
375      * all properties. If no properties are recognized, an empty map is
376      * returned.
377      *
378      * @see #getProperty(String)
379      * @since 1.5
380      */

381     public Map JavaDoc<String JavaDoc,Object JavaDoc> properties() {
382     Map JavaDoc<String JavaDoc,Object JavaDoc> ret;
383     if (properties == null) {
384         ret = new HashMap JavaDoc<String JavaDoc,Object JavaDoc>(0);
385     } else {
386         ret = (Map JavaDoc<String JavaDoc,Object JavaDoc>) (properties.clone());
387     }
388     return (Map JavaDoc<String JavaDoc,Object JavaDoc>) Collections.unmodifiableMap(ret);
389     }
390
391
392     /**
393      * Obtain the property value specified by the key.
394      * The concept of properties is further explained in
395      * the {@link AudioFileFormat class description}.
396      *
397      * <p>If the specified property is not defined for a
398      * particular file format, this method returns
399      * <code>null</code>.
400      *
401      * @param key the key of the desired property
402      * @return the value of the property with the specified key,
403      * or <code>null</code> if the property does not exist.
404      *
405      * @see #properties
406      * @since 1.5
407      */

408     public Object JavaDoc getProperty(String JavaDoc key) {
409     if (properties == null) {
410         return null;
411     }
412     return properties.get(key);
413     }
414
415
416     /**
417      * Indicates whether this format matches the one specified. To match,
418      * two formats must have the same encoding, the same number of channels,
419      * and the same number of bits per sample and bytes per frame.
420      * The two formats must also have the same sample rate,
421      * unless the specified format has the sample rate value <code>AudioSystem.NOT_SPECIFIED</code>,
422      * which any sample rate will match. The frame rates must
423      * similarly be equal, unless the specified format has the frame rate
424      * value <code>AudioSystem.NOT_SPECIFIED</code>. The byte order (big-endian or little-endian)
425      * must match if the sample size is greater than one byte.
426      *
427      * @param format format to test for match
428      * @return <code>true</code> if this format matches the one specified,
429      * <code>false</code> otherwise.
430      */

431     /*
432      * $$kk: 04.20.99: i changed the semantics of this.
433      */

434     public boolean matches(AudioFormat JavaDoc format) {
435
436     if (format.getEncoding().equals(getEncoding()) &&
437         ( (format.getSampleRate() == (float)AudioSystem.NOT_SPECIFIED) || (format.getSampleRate() == getSampleRate()) ) &&
438         (format.getSampleSizeInBits() == getSampleSizeInBits()) &&
439         (format.getChannels() == getChannels() &&
440          (format.getFrameSize() == getFrameSize()) &&
441          ( (format.getFrameRate() == (float)AudioSystem.NOT_SPECIFIED) || (format.getFrameRate() == getFrameRate()) ) &&
442          ( (format.getSampleSizeInBits() <= 8) || (format.isBigEndian() == isBigEndian()) ) ) )
443         return true;
444
445     return false;
446     }
447
448
449     /**
450      * Returns a string that describes the format, such as:
451      * "PCM SIGNED 22050 Hz 16 bit mono big-endian". The contents of the string
452      * may vary between implementations of Java Sound.
453      *
454      * @return a string that describes the format parameters
455      */

456     public String JavaDoc toString() {
457     String JavaDoc sEncoding = "";
458     if (getEncoding() != null) {
459         sEncoding = getEncoding().toString() + " ";
460     }
461
462     String JavaDoc sSampleRate;
463     if (getSampleRate() == (float) AudioSystem.NOT_SPECIFIED) {
464         sSampleRate = "unknown sample rate, ";
465     } else {
466         sSampleRate = "" + getSampleRate() + " Hz, ";
467     }
468
469     String JavaDoc sSampleSizeInBits;
470     if (getSampleSizeInBits() == (float) AudioSystem.NOT_SPECIFIED) {
471         sSampleSizeInBits = "unknown bits per sample, ";
472     } else {
473         sSampleSizeInBits = "" + getSampleSizeInBits() + " bit, ";
474     }
475
476     String JavaDoc sChannels;
477     if (getChannels() == 1) {
478         sChannels = "mono, ";
479     } else
480         if (getChannels() == 2) {
481         sChannels = "stereo, ";
482         } else {
483         if (getChannels() == AudioSystem.NOT_SPECIFIED) {
484             sChannels = " unknown number of channels, ";
485         } else {
486             sChannels = ""+getChannels()+" channels, ";
487         }
488         }
489
490     String JavaDoc sFrameSize;
491     if (getFrameSize() == (float) AudioSystem.NOT_SPECIFIED) {
492         sFrameSize = "unknown frame size, ";
493     } else {
494         sFrameSize = "" + getFrameSize()+ " bytes/frame, ";
495     }
496
497         String JavaDoc sFrameRate = "";
498         if (Math.abs(getSampleRate() - getFrameRate()) > 0.00001) {
499         if (getFrameRate() == (float) AudioSystem.NOT_SPECIFIED) {
500         sFrameRate = "unknown frame rate, ";
501         } else {
502         sFrameRate = getFrameRate() + " frames/second, ";
503         }
504     }
505
506     String JavaDoc sEndian = "";
507     if ((getEncoding().equals(Encoding.PCM_SIGNED)
508          || getEncoding().equals(Encoding.PCM_UNSIGNED))
509         && ((getSampleSizeInBits() > 8)
510             || (getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED))) {
511         if (isBigEndian()) {
512         sEndian = "big-endian";
513         } else {
514         sEndian = "little-endian";
515         }
516     }
517
518     return sEncoding
519         + sSampleRate
520         + sSampleSizeInBits
521         + sChannels
522         + sFrameSize
523         + sFrameRate
524         + sEndian;
525
526     }
527
528     /**
529      * The <code>Encoding</code> class names the specific type of data representation
530      * used for an audio stream. The encoding includes aspects of the
531      * sound format other than the number of channels, sample rate, sample size,
532      * frame rate, frame size, and byte order.
533      * <p>
534      * One ubiquitous type of audio encoding is pulse-code modulation (PCM),
535      * which is simply a linear (proportional) representation of the sound
536      * waveform. With PCM, the number stored in each sample is proportional
537      * to the instantaneous amplitude of the sound pressure at that point in
538      * time. The numbers are frequently signed or unsigned integers.
539      * Besides PCM, other encodings include mu-law and a-law, which are nonlinear
540      * mappings of the sound amplitude that are often used for recording speech.
541      * <p>
542      * You can use a predefined encoding by referring to one of the static
543      * objects created by this class, such as PCM_SIGNED or
544      * PCM_UNSIGNED. Service providers can create new encodings, such as
545      * compressed audio formats or floating-point PCM samples, and make
546      * these available through the <code>{@link AudioSystem}</code> class.
547      * <p>
548      * The <code>Encoding</code> class is static, so that all
549      * <code>AudioFormat</code> objects that have the same encoding will refer
550      * to the same object (rather than different instances of the same class).
551      * This allows matches to be made by checking that two format's encodings
552      * are equal.
553      *
554      * @see AudioFormat
555      * @see javax.sound.sampled.spi.FormatConversionProvider
556      *
557      * @author Kara Kytle
558      * @version 1.35 04/03/15
559      * @since 1.3
560      */

561     public static class Encoding {
562
563
564     // ENCODING DEFINES
565

566     /**
567      * Specifies signed, linear PCM data.
568      */

569     public static final Encoding PCM_SIGNED = new Encoding("PCM_SIGNED");
570
571     /**
572      * Specifies unsigned, linear PCM data.
573      */

574     public static final Encoding PCM_UNSIGNED = new Encoding("PCM_UNSIGNED");
575
576     /**
577      * Specifies u-law encoded data.
578      */

579     public static final Encoding ULAW = new Encoding("ULAW");
580
581     /**
582      * Specifies a-law encoded data.
583      */

584     public static final Encoding ALAW = new Encoding("ALAW");
585
586
587     // INSTANCE VARIABLES
588

589     /**
590      * Encoding name.
591      */

592     private String JavaDoc name;
593
594
595     // CONSTRUCTOR
596

597     /**
598      * Constructs a new encoding.
599      * @param name the name of the new type of encoding
600      */

601     public Encoding(String JavaDoc name) {
602         this.name = name;
603     }
604
605
606     // METHODS
607

608     /**
609      * Finalizes the equals method
610      */

611     public final boolean equals(Object JavaDoc obj) {
612         if (toString() == null) {
613         return (obj != null) && (obj.toString() == null);
614         }
615         if (obj instanceof Encoding) {
616         return toString().equals(obj.toString());
617         }
618         return false;
619     }
620
621     /**
622      * Finalizes the hashCode method
623      */

624     public final int hashCode() {
625         if (toString() == null) {
626         return 0;
627         }
628         return toString().hashCode();
629     }
630
631     /**
632      * Provides the <code>String</code> representation of the encoding. This <code>String</code> is
633      * the same name that was passed to the constructor. For the predefined encodings, the name
634      * is similar to the encoding's variable (field) name. For example, <code>PCM_SIGNED.toString()</code> returns
635      * the name "pcm_signed".
636      *
637      * @return the encoding name
638      */

639     public final String JavaDoc toString() {
640         return name;
641     }
642
643     } // class Encoding
644
}
645
646
Popular Tags