KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)AudioSystem.java 1.81 04/07/14
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.io.File JavaDoc;
11 import java.io.InputStream JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.io.OutputStream JavaDoc;
14 import java.net.URL JavaDoc;
15
16 import java.util.HashSet JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Set JavaDoc;
19 import java.util.Vector JavaDoc;
20 import java.util.ArrayList JavaDoc;
21
22 import javax.sound.sampled.spi.AudioFileWriter JavaDoc;
23 import javax.sound.sampled.spi.AudioFileReader JavaDoc;
24 import javax.sound.sampled.spi.FormatConversionProvider JavaDoc;
25 import javax.sound.sampled.spi.MixerProvider JavaDoc;
26
27 import com.sun.media.sound.JDK13Services;
28
29 /* $fb TODO:
30  * - consistent usage of (typed) collections
31  */

32
33
34 /**
35  * The <code>AudioSystem</code> class acts as the entry point to the
36  * sampled-audio system resources. This class lets you query and
37  * access the mixers that are installed on the system.
38  * <code>AudioSystem</code> includes a number of
39  * methods for converting audio data between different formats, and for
40  * translating between audio files and streams. It also provides a method
41  * for obtaining a <code>{@link Line}</code> directly from the
42  * <code>AudioSystem</code> without dealing explicitly
43  * with mixers.
44  *
45  * <p>Properties can be used to specify the default mixer
46  * for specific line types.
47  * Both system properties and a properties file are considered.
48  * In the Sun reference implementation, the properties file is
49  * &quot;lib/sound.properties&quot; in the JRE
50  * directory. If a property exists both as a system property and in the
51  * properties file, the system property takes precedence. If none is
52  * specified, a suitable default is chosen among the available devices.
53  * The syntax of the properties file is specified in
54  * {@link java.util.Properties#load(InputStream) Properties.load}. The
55  * following table lists the available property keys and which methods
56  * consider them:
57  *
58  * <table border=0>
59  * <tr>
60  * <th>Property Key</th>
61  * <th>Interface</th>
62  * <th>Affected Method(s)</th>
63  * </tr>
64  * <tr>
65  * <td><code>javax.sound.sampled.Clip</code></td>
66  * <td>{@link Clip}</td>
67  * <td>{@link #getLine}, {@link #getClip}</td>
68  * </tr>
69  * <tr>
70  * <td><code>javax.sound.sampled.Port</code></td>
71  * <td>{@link Port}</td>
72  * <td>{@link #getLine}</td>
73  * </tr>
74  * <tr>
75  * <td><code>javax.sound.sampled.SourceDataLine</code></td>
76  * <td>{@link SourceDataLine}</td>
77  * <td>{@link #getLine}, {@link #getSourceDataLine}</td>
78  * </tr>
79  * <tr>
80  * <td><code>javax.sound.sampled.TargetDataLine</code></td>
81  * <td>{@link TargetDataLine}</td>
82  * <td>{@link #getLine}, {@link #getTargetDataLine}</td>
83  * </tr>
84  * </table>
85  *
86  * The property value consists of the provider class name
87  * and the mixer name, separated by the hash mark (&quot;#&quot;).
88  * The provider class name is the fully-qualified
89  * name of a concrete {@link javax.sound.sampled.spi.MixerProvider
90  * mixer provider} class. The mixer name is matched against
91  * the <code>String</code> returned by the <code>getName</code>
92  * method of <code>Mixer.Info</code>.
93  * Either the class name, or the mixer name may be omitted.
94  * If only the class name is specified, the trailing hash mark
95  * is optional.
96  *
97  * <p>If the provider class is specified, and it can be
98  * successully retrieved from the installed providers, the list of
99  * <code>Mixer.Info</code> objects is retrieved
100  * from the provider. Otherwise, or when these mixers
101  * do not provide a subsequent match, the list is retrieved
102  * from {@link #getMixerInfo} to contain
103  * all available <code>Mixer.Info</code> objects.
104  *
105  * <p>If a mixer name is specified, the resulting list of
106  * <code>Mixer.Info</code> objects is searched:
107  * the first one with a matching name, and whose
108  * <code>Mixer</code> provides the
109  * respective line interface, will be returned.
110  * If no matching <code>Mixer.Info</code> object
111  * is found, or the mixer name is not specified,
112  * the first mixer from the resulting
113  * list, which provides the respective line
114  * interface, will be returned.
115  *
116  * For example, the property <code>javax.sound.sampled.Clip</code>
117  * with a value
118  * <code>&quot;com.sun.media.sound.MixerProvider#SunClip&quot;</code>
119  * will have the following consequences when
120  * <code>getLine</code> is called requesting a <code>Clip</code>
121  * instance:
122  * if the class <code>com.sun.media.sound.MixerProvider</code> exists
123  * in the list of installed mixer providers,
124  * the first <code>Clip</code> from the first mixer with name
125  * <code>&quot;SunClip&quot;</code> will be returned. If it cannot
126  * be found, the first <code>Clip</code> from the first mixer
127  * of the specified provider will be returned, regardless of name.
128  * If there is none, the first <code>Clip</code> from the first
129  * <code>Mixer</code> with name
130  * <code>&quot;SunClip&quot;</code> in the list of all mixers
131  * (as returned by <code>getMixerInfo</code>) will be returned,
132  * or, if not found, the first <code>Clip</code> of the first
133  * <code>Mixer</code>that can be found in the list of all
134  * mixers is returned.
135  * If that fails, too, an <code>IllegalArgumentException</code>
136  * is thrown.
137  *
138  * @author Kara Kytle
139  * @author Florian Bomers
140  * @author Matthias Pfisterer
141  * @author Kevin P. Smith
142  * @version 1.81, 04/07/14
143  *
144  * @see AudioFormat
145  * @see AudioInputStream
146  * @see Mixer
147  * @see Line
148  * @see Line.Info
149  * @since 1.3
150  */

151 public class AudioSystem {
152
153     /**
154      * An integer that stands for an unknown numeric value.
155      * This value is appropriate only for signed quantities that do not
156      * normally take negative values. Examples include file sizes, frame
157      * sizes, buffer sizes, and sample rates.
158      * A number of Java Sound constructors accept
159      * a value of <code>NOT_SPECIFIED</code> for such parameters. Other
160      * methods may also accept or return this value, as documented.
161      */

162     public static final int NOT_SPECIFIED = -1;
163
164     /**
165      * Private no-args constructor for ensuring against instantiation.
166      */

167     private AudioSystem() {
168     }
169
170
171     /**
172      * Obtains an array of mixer info objects that represents
173      * the set of audio mixers that are currently installed on the system.
174      * @return an array of info objects for the currently installed mixers. If no mixers
175      * are available on the system, an array of length 0 is returned.
176      * @see #getMixer
177      */

178     public static Mixer.Info JavaDoc[] getMixerInfo() {
179
180     List JavaDoc infos = getMixerInfoList();
181     Mixer.Info JavaDoc[] allInfos = (Mixer.Info JavaDoc[]) infos.toArray(new Mixer.Info JavaDoc[infos.size()]);
182     return allInfos;
183     }
184
185
186     /**
187      * Obtains the requested audio mixer.
188      * @param info a <code>Mixer.Info</code> object representing the desired
189      * mixer, or <code>null</code> for the system default mixer
190      * @return the requested mixer
191      * @throws SecurityException if the requested mixer
192      * is unavailable because of security restrictions
193      * @throws IllegalArgumentException if the info object does not represent
194      * a mixer installed on the system
195      * @see #getMixerInfo
196      */

197     public static Mixer JavaDoc getMixer(Mixer.Info JavaDoc info) {
198
199     Mixer JavaDoc mixer = null;
200     List JavaDoc providers = getMixerProviders();
201
202     for(int i = 0; i < providers.size(); i++ ) {
203
204         try {
205         return ((MixerProvider JavaDoc)providers.get(i)).getMixer(info);
206
207         } catch (IllegalArgumentException JavaDoc e) {
208         } catch (NullPointerException JavaDoc e) {
209         // $$jb 08.20.99: If the strings in the info object aren't
210
// set, then Netscape (using jdk1.1.5) tends to throw
211
// NPE's when doing some string manipulation. This is
212
// probably not the best fix, but is solves the problem
213
// of the NPE in Netscape using local classes
214
// $$jb 11.01.99: Replacing this patch.
215
}
216     }
217
218     //$$fb if looking for default mixer, and not found yet, add a round of looking
219
if (info == null) {
220         for(int i = 0; i < providers.size(); i++ ) {
221         try {
222             MixerProvider JavaDoc provider = (MixerProvider JavaDoc) providers.get(i);
223             Mixer.Info JavaDoc[] infos = provider.getMixerInfo();
224             // start from 0 to last device (do not reverse this order)
225
for (int ii = 0; ii < infos.length; ii++) {
226             try {
227                 return provider.getMixer(infos[ii]);
228             } catch (IllegalArgumentException JavaDoc e) {
229                 // this is not a good default device :)
230
}
231             }
232         } catch (IllegalArgumentException JavaDoc e) {
233         } catch (NullPointerException JavaDoc e) {
234         }
235         }
236     }
237
238
239     throw new IllegalArgumentException JavaDoc("Mixer not supported: "
240                        + (info!=null?info.toString():"null"));
241     }
242
243
244     //$$fb 2002-11-26: fix for 4757930: DOC: AudioSystem.getTarget/SourceLineInfo() is ambiguous
245
/**
246      * Obtains information about all source lines of a particular type that are supported
247      * by the installed mixers.
248      * @param info a <code>Line.Info</code> object that specifies the kind of
249      * lines about which information is requested
250      * @return an array of <code>Line.Info</code> objects describing source lines matching
251      * the type requested. If no matching source lines are supported, an array of length 0
252      * is returned.
253      *
254      * @see Mixer#getSourceLineInfo(Line.Info)
255      */

256     public static Line.Info JavaDoc[] getSourceLineInfo(Line.Info JavaDoc info) {
257
258     Vector JavaDoc vector = new Vector JavaDoc();
259     Line.Info JavaDoc[] currentInfoArray;
260
261     Mixer JavaDoc mixer;
262     Line.Info JavaDoc fullInfo = null;
263     Mixer.Info JavaDoc[] infoArray = getMixerInfo();
264
265     for (int i = 0; i < infoArray.length; i++) {
266
267         mixer = getMixer(infoArray[i]);
268
269         currentInfoArray = mixer.getSourceLineInfo(info);
270         for (int j = 0; j < currentInfoArray.length; j++) {
271         vector.addElement(currentInfoArray[j]);
272         }
273     }
274
275     Line.Info JavaDoc[] returnedArray = new Line.Info JavaDoc[vector.size()];
276
277     for (int i = 0; i < returnedArray.length; i++) {
278         returnedArray[i] = (Line.Info JavaDoc)vector.get(i);
279     }
280
281     return returnedArray;
282     }
283
284
285     /**
286      * Obtains information about all target lines of a particular type that are supported
287      * by the installed mixers.
288      * @param info a <code>Line.Info</code> object that specifies the kind of
289      * lines about which information is requested
290      * @return an array of <code>Line.Info</code> objects describing target lines matching
291      * the type requested. If no matching target lines are supported, an array of length 0
292      * is returned.
293      *
294      * @see Mixer#getTargetLineInfo(Line.Info)
295      */

296     public static Line.Info JavaDoc[] getTargetLineInfo(Line.Info JavaDoc info) {
297
298     Vector JavaDoc vector = new Vector JavaDoc();
299     Line.Info JavaDoc[] currentInfoArray;
300
301     Mixer JavaDoc mixer;
302     Line.Info JavaDoc fullInfo = null;
303     Mixer.Info JavaDoc[] infoArray = getMixerInfo();
304
305     for (int i = 0; i < infoArray.length; i++) {
306
307         mixer = getMixer(infoArray[i]);
308
309         currentInfoArray = mixer.getTargetLineInfo(info);
310         for (int j = 0; j < currentInfoArray.length; j++) {
311         vector.addElement(currentInfoArray[j]);
312         }
313     }
314
315     Line.Info JavaDoc[] returnedArray = new Line.Info JavaDoc[vector.size()];
316
317     for (int i = 0; i < returnedArray.length; i++) {
318         returnedArray[i] = (Line.Info JavaDoc)vector.get(i);
319     }
320
321     return returnedArray;
322     }
323
324
325     /**
326      * Indicates whether the system supports any lines that match
327      * the specified <code>Line.Info</code> object. A line is supported if
328      * any installed mixer supports it.
329      * @param info a <code>Line.Info</code> object describing the line for which support is queried
330      * @return <code>true</code> if at least one matching line is
331      * supported, otherwise <code>false</code>
332      *
333      * @see Mixer#isLineSupported(Line.Info)
334      */

335     public static boolean isLineSupported(Line.Info JavaDoc info) {
336
337     Mixer JavaDoc mixer;
338     Mixer.Info JavaDoc[] infoArray = getMixerInfo();
339
340     for (int i = 0; i < infoArray.length; i++) {
341
342         if( infoArray[i] != null ) {
343         mixer = getMixer(infoArray[i]);
344         if (mixer.isLineSupported(info)) {
345             return true;
346         }
347         }
348     }
349
350     return false;
351     }
352
353     /**
354      * Obtains a line that matches the description in the specified
355      * <code>Line.Info</code> object.
356      *
357      * <p>If a <code>DataLine</code> is requested, and <code>info</code>
358      * is an instance of <code>DataLine.Info</code> specifying at least
359      * one fully qualified audio format, the last one
360      * will be used as the default format of the returned
361      * <code>DataLine</code>.
362      *
363      * <p>If system properties
364      * <code>javax.sound.sampled.Clip</code>,
365      * <code>javax.sound.sampled.Port</code>,
366      * <code>javax.sound.sampled.SourceDataLine</code> and
367      * <code>javax.sound.sampled.TargetDataLine</code> are defined
368      * or they are defined in the file &quot;sound.properties&quot;,
369      * they are used to retrieve default lines.
370      * For details, refer to the {@link AudioSystem class description}.
371      *
372      * If the respective property is not set, or the mixer
373      * requested in the property is not installed or does not provide the
374      * requested line, all installed mixers are queried for the
375      * requested line type. A Line will be returned from the first mixer
376      * providing the requested line type.
377      *
378      * @param info a <code>Line.Info</code> object describing the desired kind of line
379      * @return a line of the requested kind
380      *
381      * @throws LineUnavailableException if a matching line
382      * is not available due to resource restrictions
383      * @throws SecurityException if a matching line
384      * is not available due to security restrictions
385      * @throws IllegalArgumentException if the system does not
386      * support at least one line matching the specified
387      * <code>Line.Info</code> object
388      * through any installed mixer
389      */

390     public static Line JavaDoc getLine(Line.Info JavaDoc info) throws LineUnavailableException JavaDoc {
391     LineUnavailableException JavaDoc lue = null;
392     List JavaDoc providers = getMixerProviders();
393
394
395     // 1: try from default mixer for this line class
396
try {
397         Mixer JavaDoc mixer = getDefaultMixer(providers, info);
398         if (mixer != null && mixer.isLineSupported(info)) {
399         return mixer.getLine(info);
400         }
401     } catch (LineUnavailableException JavaDoc e) {
402         lue = e;
403     } catch (IllegalArgumentException JavaDoc iae) {
404         // must not happen... but better to catch it here,
405
// if plug-ins are badly written
406
}
407
408
409     // 2: if that doesn't work, try to find any mixing mixer
410
for(int i = 0; i < providers.size(); i++) {
411         MixerProvider JavaDoc provider = (MixerProvider JavaDoc) providers.get(i);
412         Mixer.Info JavaDoc[] infos = provider.getMixerInfo();
413
414         for (int j = 0; j < infos.length; j++) {
415         try {
416             Mixer JavaDoc mixer = provider.getMixer(infos[j]);
417             // see if this is an appropriate mixer which can mix
418
if (isAppropriateMixer(mixer, info, true)) {
419             return mixer.getLine(info);
420             }
421         } catch (LineUnavailableException JavaDoc e) {
422             lue = e;
423         } catch (IllegalArgumentException JavaDoc iae) {
424             // must not happen... but better to catch it here,
425
// if plug-ins are badly written
426
}
427         }
428     }
429
430
431     // 3: if that didn't work, try to find any non-mixing mixer
432
for(int i = 0; i < providers.size(); i++) {
433         MixerProvider JavaDoc provider = (MixerProvider JavaDoc) providers.get(i);
434         Mixer.Info JavaDoc[] infos = provider.getMixerInfo();
435         for (int j = 0; j < infos.length; j++) {
436         try {
437             Mixer JavaDoc mixer = provider.getMixer(infos[j]);
438             // see if this is an appropriate mixer which can mix
439
if (isAppropriateMixer(mixer, info, false)) {
440             return mixer.getLine(info);
441             }
442         } catch (LineUnavailableException JavaDoc e) {
443             lue = e;
444         } catch (IllegalArgumentException JavaDoc iae) {
445             // must not happen... but better to catch it here,
446
// if plug-ins are badly written
447
}
448         }
449     }
450
451     // if this line was supported but was not available, throw the last
452
// LineUnavailableException we got (??).
453
if (lue != null) {
454         throw lue;
455     }
456
457     // otherwise, the requested line was not supported, so throw
458
// an Illegal argument exception
459
throw new IllegalArgumentException JavaDoc("No line matching " +
460                        info.toString() + " is supported.");
461     }
462
463
464     /**
465      * Obtains a clip that can be used for playing back
466      * an audio file or an audio stream. The returned clip
467      * will be provided by the default system mixer, or,
468      * if not possible, by any other mixer installed in the
469      * system that supports a <code>Clip</code>
470      * object.
471      *
472      * <p>The returned clip must be opened with the
473      * <code>open(AudioFormat)</code> or
474      * <code>open(AudioInputStream)</code> method.
475      *
476      * <p>This is a high-level method that uses <code>getMixer</code>
477      * and <getLine</code> internally.
478      *
479      * <p>If the system property
480      * <code>javax.sound.sampled.Clip</code>
481      * is defined or it is defined in the file &quot;sound.properties&quot;,
482      * it is used to retrieve the default clip.
483      * For details, refer to the {@link AudioSystem class description}.
484      *
485      * @return the desired clip object
486      *
487      * @throws LineUnavailableException if a clip object
488      * is not available due to resource restrictions
489      * @throws SecurityException if a clip object
490      * is not available due to security restrictions
491      * @throws IllegalArgumentException if the system does not
492      * support at least one clip instance through any installed mixer
493      *
494      * @see #getClip(Mixer.Info)
495      * @since 1.5
496      */

497     public static Clip JavaDoc getClip() throws LineUnavailableException JavaDoc{
498     AudioFormat JavaDoc format = new AudioFormat JavaDoc(AudioFormat.Encoding.PCM_SIGNED,
499                          AudioSystem.NOT_SPECIFIED,
500                          16, 2, 4,
501                          AudioSystem.NOT_SPECIFIED, true);
502     DataLine.Info JavaDoc info = new DataLine.Info JavaDoc(Clip JavaDoc.class, format);
503     return (Clip JavaDoc) AudioSystem.getLine(info);
504     }
505
506
507     /**
508      * Obtains a clip from the specified mixer that can be
509      * used for playing back an audio file or an audio stream.
510      *
511      * <p>The returned clip must be opened with the
512      * <code>open(AudioFormat)</code> or
513      * <code>open(AudioInputStream)</code> method.
514      *
515      * <p>This is a high-level method that uses <code>getMixer</code>
516      * and <getLine</code> internally.
517      *
518      * @param mixerInfo a <code>Mixer.Info</code> object representing the
519      * desired mixer, or <code>null</code> for the system default mixer
520      * @return a clip object from the specified mixer
521      *
522      * @throws LineUnavailableException if a clip
523      * is not available from this mixer due to resource restrictions
524      * @throws SecurityException if a clip
525      * is not available from this mixer due to security restrictions
526      * @throws IllegalArgumentException if the system does not
527      * support at least one clip through the specified mixer
528      *
529      * @see #getClip()
530      * @since 1.5
531      */

532     public static Clip JavaDoc getClip(Mixer.Info JavaDoc mixerInfo) throws LineUnavailableException JavaDoc{
533     AudioFormat JavaDoc format = new AudioFormat JavaDoc(AudioFormat.Encoding.PCM_SIGNED,
534                          AudioSystem.NOT_SPECIFIED,
535                          16, 2, 4,
536                          AudioSystem.NOT_SPECIFIED, true);
537     DataLine.Info JavaDoc info = new DataLine.Info JavaDoc(Clip JavaDoc.class, format);
538     Mixer JavaDoc mixer = AudioSystem.getMixer(mixerInfo);
539     return (Clip JavaDoc) mixer.getLine(info);
540     }
541
542
543     /**
544      * Obtains a source data line that can be used for playing back
545      * audio data in the format specified by the
546      * <code>AudioFormat</code> object. The returned line
547      * will be provided by the default system mixer, or,
548      * if not possible, by any other mixer installed in the
549      * system that supports a matching
550      * <code>SourceDataLine</code> object.
551      *
552      * <p>The returned line should be opened with the
553      * <code>open(AudioFormat)</code> or
554      * <code>open(AudioFormat, int)</code> method.
555      *
556      * <p>This is a high-level method that uses <code>getMixer</code>
557      * and <getLine</code> internally.
558      *
559      * <p>The returned <code>SourceDataLine</code>'s default
560      * audio format will be initialized with <code>format</code>.
561      *
562      * <p>If the system property
563      * <code>javax.sound.sampled.SourceDataLine</code>
564      * is defined or it is defined in the file &quot;sound.properties&quot;,
565      * it is used to retrieve the default source data line.
566      * For details, refer to the {@link AudioSystem class description}.
567      *
568      * @param format an <code>AudioFormat</code> object specifying
569      * the supported audio format of the returned line,
570      * or <code>null</code> for any audio format
571      * @return the desired <code>SourceDataLine</code> object
572      *
573      * @throws LineUnavailableException if a matching source data line
574      * is not available due to resource restrictions
575      * @throws SecurityException if a matching source data line
576      * is not available due to security restrictions
577      * @throws IllegalArgumentException if the system does not
578      * support at least one source data line supporting the
579      * specified audio format through any installed mixer
580      *
581      * @see #getSourceDataLine(AudioFormat, Mixer.Info)
582      * @since 1.5
583      */

584     public static SourceDataLine JavaDoc getSourceDataLine(AudioFormat JavaDoc format)
585         throws LineUnavailableException JavaDoc{
586     DataLine.Info JavaDoc info = new DataLine.Info JavaDoc(SourceDataLine JavaDoc.class, format);
587     return (SourceDataLine JavaDoc) AudioSystem.getLine(info);
588     }
589
590
591     /**
592      * Obtains a source data line that can be used for playing back
593      * audio data in the format specified by the
594      * <code>AudioFormat</code> object, provided by the mixer
595      * specified by the <code>Mixer.Info</code> object.
596      *
597      * <p>The returned line should be opened with the
598      * <code>open(AudioFormat)</code> or
599      * <code>open(AudioFormat, int)</code> method.
600      *
601      * <p>This is a high-level method that uses <code>getMixer</code>
602      * and <getLine</code> internally.
603      *
604      * <p>The returned <code>SourceDataLine</code>'s default
605      * audio format will be initialized with <code>format</code>.
606      *
607      * @param format an <code>AudioFormat</code> object specifying
608      * the supported audio format of the returned line,
609      * or <code>null</code> for any audio format
610      * @param mixerinfo a <code>Mixer.Info</code> object representing
611      * the desired mixer, or <code>null</code> for the system
612      * default mixer
613      * @return the desired <code>SourceDataLine</code> object
614      *
615      * @throws LineUnavailableException if a matching source data
616      * line is not available from the specified mixer due
617      * to resource restrictions
618      * @throws SecurityException if a matching source data line
619      * is not available from the specified mixer due to
620      * security restrictions
621      * @throws IllegalArgumentException if the specified mixer does
622      * not support at least one source data line supporting
623      * the specified audio format
624      *
625      * @see #getSourceDataLine(AudioFormat)
626      * @since 1.5
627      */

628     public static SourceDataLine JavaDoc getSourceDataLine(AudioFormat JavaDoc format,
629                            Mixer.Info JavaDoc mixerinfo)
630         throws LineUnavailableException JavaDoc{
631     DataLine.Info JavaDoc info = new DataLine.Info JavaDoc(SourceDataLine JavaDoc.class, format);
632     Mixer JavaDoc mixer = AudioSystem.getMixer(mixerinfo);
633     return (SourceDataLine JavaDoc) mixer.getLine(info);
634   }
635
636
637     /**
638      * Obtains a target data line that can be used for recording
639      * audio data in the format specified by the
640      * <code>AudioFormat</code> object. The returned line
641      * will be provided by the default system mixer, or,
642      * if not possible, by any other mixer installed in the
643      * system that supports a matching
644      * <code>TargetDataLine</code> object.
645      *
646      * <p>The returned line should be opened with the
647      * <code>open(AudioFormat)</code> or
648      * <code>open(AudioFormat, int)</code> method.
649      *
650      * <p>This is a high-level method that uses <code>getMixer</code>
651      * and <getLine</code> internally.
652      *
653      * <p>The returned <code>TargetDataLine</code>'s default
654      * audio format will be initialized with <code>format</code>.
655      *
656      * @param format an <code>AudioFormat</code> object specifying
657      * the supported audio format of the returned line,
658      * or <code>null</code> for any audio format
659      * @return the desired <code>TargetDataLine</code> object
660      *
661      * @throws LineUnavailableException if a matching target data line
662      * is not available due to resource restrictions
663      * @throws SecurityException if a matching target data line
664      * is not available due to security restrictions
665      * @throws IllegalArgumentException if the system does not
666      * support at least one target data line supporting the
667      * specified audio format through any installed mixer
668      *
669      * @see #getTargetDataLine(AudioFormat, Mixer.Info)
670      * @see AudioPermission
671      * @since 1.5
672      */

673     public static TargetDataLine JavaDoc getTargetDataLine(AudioFormat JavaDoc format)
674     throws LineUnavailableException JavaDoc{
675
676     DataLine.Info JavaDoc info = new DataLine.Info JavaDoc(TargetDataLine JavaDoc.class, format);
677     return (TargetDataLine JavaDoc) AudioSystem.getLine(info);
678     }
679
680
681
682     /**
683      * Obtains a target data line that can be used for recording
684      * audio data in the format specified by the
685      * <code>AudioFormat</code> object, provided by the mixer
686      * specified by the <code>Mixer.Info</code> object.
687      *
688      * <p>The returned line should be opened with the
689      * <code>open(AudioFormat)</code> or
690      * <code>open(AudioFormat, int)</code> method.
691      *
692      * <p>This is a high-level method that uses <code>getMixer</code>
693      * and <getLine</code> internally.
694      *
695      * <p>The returned <code>TargetDataLine</code>'s default
696      * audio format will be initialized with <code>format</code>.
697      *
698      * <p>If the system property
699      * <code>javax.sound.sampled.TargetDataLine</code>
700      * is defined or it is defined in the file &quot;sound.properties&quot;,
701      * it is used to retrieve the default target data line.
702      * For details, refer to the {@link AudioSystem class description}.
703      *
704      * @param format an <code>AudioFormat</code> object specifying
705      * the supported audio format of the returned line,
706      * or <code>null</code> for any audio format
707      * @param mixerinfo a <code>Mixer.Info</code> object representing the
708      * desired mixer, or <code>null</code> for the system default mixer
709      * @return the desired <code>TargetDataLine</code> object
710      *
711      * @throws LineUnavailableException if a matching target data
712      * line is not available from the specified mixer due
713      * to resource restrictions
714      * @throws SecurityException if a matching target data line
715      * is not available from the specified mixer due to
716      * security restrictions
717      * @throws IllegalArgumentException if the specified mixer does
718      * not support at least one target data line supporting
719      * the specified audio format
720      *
721      * @see #getTargetDataLine(AudioFormat)
722      * @see AudioPermission
723      * @since 1.5
724      */

725     public static TargetDataLine JavaDoc getTargetDataLine(AudioFormat JavaDoc format,
726                            Mixer.Info JavaDoc mixerinfo)
727     throws LineUnavailableException JavaDoc {
728
729     DataLine.Info JavaDoc info = new DataLine.Info JavaDoc(TargetDataLine JavaDoc.class, format);
730     Mixer JavaDoc mixer = AudioSystem.getMixer(mixerinfo);
731     return (TargetDataLine JavaDoc) mixer.getLine(info);
732     }
733
734
735     // $$fb 2002-04-12: fix for 4662082: behavior of AudioSystem.getTargetEncodings() methods doesn't match the spec
736
/**
737      * Obtains the encodings that the system can obtain from an
738      * audio input stream with the specified encoding using the set
739      * of installed format converters.
740      * @param sourceEncoding the encoding for which conversion support
741      * is queried
742      * @return array of encodings. If <code>sourceEncoding</code>is not supported,
743      * an array of length 0 is returned. Otherwise, the array will have a length
744      * of at least 1, representing <code>sourceEncoding</code> (no conversion).
745      */

746     public static AudioFormat.Encoding JavaDoc[] getTargetEncodings(AudioFormat.Encoding JavaDoc sourceEncoding) {
747
748     List JavaDoc codecs = getFormatConversionProviders();
749     Vector JavaDoc encodings = new Vector JavaDoc();
750
751     AudioFormat.Encoding JavaDoc encs[] = null;
752
753     // gather from all the codecs
754
for(int i=0; i<codecs.size(); i++ ) {
755         FormatConversionProvider JavaDoc codec = (FormatConversionProvider JavaDoc) codecs.get(i);
756         if( codec.isSourceEncodingSupported( sourceEncoding ) ) {
757         encs = codec.getTargetEncodings();
758         for (int j = 0; j < encs.length; j++) {
759             encodings.addElement( encs[j] );
760         }
761         }
762     }
763     AudioFormat.Encoding JavaDoc encs2[] = (AudioFormat.Encoding JavaDoc[]) encodings.toArray(new AudioFormat.Encoding JavaDoc[0]);
764     return encs2;
765     }
766
767
768
769     // $$fb 2002-04-12: fix for 4662082: behavior of AudioSystem.getTargetEncodings() methods doesn't match the spec
770
/**
771      * Obtains the encodings that the system can obtain from an
772      * audio input stream with the specified format using the set
773      * of installed format converters.
774      * @param sourceFormat the audio format for which conversion
775      * is queried
776      * @return array of encodings. If <code>sourceFormat</code>is not supported,
777      * an array of length 0 is returned. Otherwise, the array will have a length
778      * of at least 1, representing the encoding of <code>sourceFormat</code> (no conversion).
779      */

780     public static AudioFormat.Encoding JavaDoc[] getTargetEncodings(AudioFormat JavaDoc sourceFormat) {
781
782
783     List JavaDoc codecs = getFormatConversionProviders();
784     Vector JavaDoc encodings = new Vector JavaDoc();
785
786     int size = 0;
787     int index = 0;
788     AudioFormat.Encoding JavaDoc encs[] = null;
789
790     // gather from all the codecs
791

792     for(int i=0; i<codecs.size(); i++ ) {
793         encs = ((FormatConversionProvider JavaDoc) codecs.get(i)).getTargetEncodings(sourceFormat);
794         size += encs.length;
795         encodings.addElement( encs );
796     }
797
798     // now build a new array
799

800     AudioFormat.Encoding JavaDoc encs2[] = new AudioFormat.Encoding JavaDoc[size];
801     for(int i=0; i<encodings.size(); i++ ) {
802         encs = (AudioFormat.Encoding JavaDoc [])(encodings.get(i));
803         for(int j=0; j<encs.length; j++ ) {
804         encs2[index++] = encs[j];
805         }
806     }
807     return encs2;
808     }
809
810
811     /**
812      * Indicates whether an audio input stream of the specified encoding
813      * can be obtained from an audio input stream that has the specified
814      * format.
815      * @param targetEncoding the desired encoding after conversion
816      * @param sourceFormat the audio format before conversion
817      * @return <code>true</code> if the conversion is supported,
818      * otherwise <code>false</code>
819      */

820     public static boolean isConversionSupported(AudioFormat.Encoding JavaDoc targetEncoding, AudioFormat JavaDoc sourceFormat) {
821
822
823     List JavaDoc codecs = getFormatConversionProviders();
824
825     for(int i=0; i<codecs.size(); i++ ) {
826         FormatConversionProvider JavaDoc codec = (FormatConversionProvider JavaDoc) codecs.get(i);
827         if(codec.isConversionSupported(targetEncoding,sourceFormat) ) {
828         return true;
829         }
830     }
831     return false;
832     }
833
834
835     /**
836      * Obtains an audio input stream of the indicated encoding, by converting the
837      * provided audio input stream.
838      * @param targetEncoding the desired encoding after conversion
839      * @param sourceStream the stream to be converted
840      * @return an audio input stream of the indicated encoding
841      * @throws IllegalArgumentException if the conversion is not supported
842      * @see #getTargetEncodings(AudioFormat.Encoding)
843      * @see #getTargetEncodings(AudioFormat)
844      * @see #isConversionSupported(AudioFormat.Encoding, AudioFormat)
845      * @see #getAudioInputStream(AudioFormat, AudioInputStream)
846      */

847     public static AudioInputStream JavaDoc getAudioInputStream(AudioFormat.Encoding JavaDoc targetEncoding,
848                                AudioInputStream JavaDoc sourceStream) {
849
850     List JavaDoc codecs = getFormatConversionProviders();
851
852     for(int i = 0; i < codecs.size(); i++) {
853         FormatConversionProvider JavaDoc codec = (FormatConversionProvider JavaDoc) codecs.get(i);
854         if( codec.isConversionSupported( targetEncoding, sourceStream.getFormat() ) ) {
855         return codec.getAudioInputStream( targetEncoding, sourceStream );
856         }
857     }
858     // we ran out of options, throw an exception
859
throw new IllegalArgumentException JavaDoc("Unsupported conversion: " + targetEncoding + " from " + sourceStream.getFormat());
860     }
861
862
863     /**
864      * Obtains the formats that have a particular encoding and that the system can
865      * obtain from a stream of the specified format using the set of
866      * installed format converters.
867      * @param targetEncoding the desired encoding after conversion
868      * @param sourceFormat the audio format before conversion
869      * @return array of formats. If no formats of the specified
870      * encoding are supported, an array of length 0 is returned.
871      */

872     public static AudioFormat JavaDoc[] getTargetFormats(AudioFormat.Encoding JavaDoc targetEncoding, AudioFormat