001/* Main interface to audio system 002 Copyright (C) 2005 Free Software Foundation, Inc. 003 004This file is part of GNU Classpath. 005 006GNU Classpath is free software; you can redistribute it and/or modify 007it under the terms of the GNU General Public License as published by 008the Free Software Foundation; either version 2, or (at your option) 009any later version. 010 011GNU Classpath is distributed in the hope that it will be useful, but 012WITHOUT ANY WARRANTY; without even the implied warranty of 013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014General Public License for more details. 015 016You should have received a copy of the GNU General Public License 017along with GNU Classpath; see the file COPYING. If not, write to the 018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 01902110-1301 USA. 020 021Linking this library statically or dynamically with other modules is 022making a combined work based on this library. Thus, the terms and 023conditions of the GNU General Public License cover the whole 024combination. 025 026As a special exception, the copyright holders of this library give you 027permission to link this library with independent modules to produce an 028executable, regardless of the license terms of these independent 029modules, and to copy and distribute the resulting executable under 030terms of your choice, provided that you also meet, for each linked 031independent module, the terms and conditions of the license of that 032module. An independent module is a module which is not derived from 033or based on this library. If you modify this library, you may extend 034this exception to your version of the library, but you are not 035obligated to do so. If you do not wish to do so, delete this 036exception statement from your version. */ 037 038 039package javax.sound.sampled; 040 041import gnu.classpath.ServiceFactory; 042 043import java.io.File; 044import java.io.IOException; 045import java.io.InputStream; 046import java.io.OutputStream; 047import java.net.URL; 048import java.util.HashSet; 049import java.util.Iterator; 050 051import javax.sound.sampled.spi.AudioFileReader; 052import javax.sound.sampled.spi.AudioFileWriter; 053import javax.sound.sampled.spi.FormatConversionProvider; 054import javax.sound.sampled.spi.MixerProvider; 055 056/** 057 * This clas is the primary interface to the audio system. It contains 058 * a number of static methods which can be used to access this package's 059 * functionality. 060 * 061 * @since 1.3 062 */ 063public class AudioSystem 064{ 065 /** 066 * A constant which can be passed to a number of methods in this package, 067 * to indicate an unspecified value. 068 */ 069 public static final int NOT_SPECIFIED = -1; 070 071 // This class is not instantiable. 072 private AudioSystem() 073 { 074 } 075 076 /** 077 * Return the file format of a given File. 078 * @param f the file to check 079 * @return the format of the file 080 * @throws UnsupportedAudioFileException if the file's format is not 081 * recognized 082 * @throws IOException if there is an I/O error reading the file 083 */ 084 public static AudioFileFormat getAudioFileFormat(File f) 085 throws UnsupportedAudioFileException, IOException 086 { 087 Iterator i = ServiceFactory.lookupProviders(AudioFileReader.class); 088 while (i.hasNext()) 089 { 090 AudioFileReader reader = (AudioFileReader) i.next(); 091 try 092 { 093 return reader.getAudioFileFormat(f); 094 } 095 catch (UnsupportedAudioFileException _) 096 { 097 // Try the next provider. 098 } 099 } 100 throw new UnsupportedAudioFileException("file type not recognized"); 101 } 102 103 /** 104 * Return the file format of a given input stream. 105 * @param is the input stream to check 106 * @return the format of the stream 107 * @throws UnsupportedAudioFileException if the stream's format is not 108 * recognized 109 * @throws IOException if there is an I/O error reading the stream 110 */ 111 public static AudioFileFormat getAudioFileFormat(InputStream is) 112 throws UnsupportedAudioFileException, IOException 113 { 114 Iterator i = ServiceFactory.lookupProviders(AudioFileReader.class); 115 while (i.hasNext()) 116 { 117 AudioFileReader reader = (AudioFileReader) i.next(); 118 try 119 { 120 return reader.getAudioFileFormat(is); 121 } 122 catch (UnsupportedAudioFileException _) 123 { 124 // Try the next provider. 125 } 126 } 127 throw new UnsupportedAudioFileException("input stream type not recognized"); 128 } 129 130 /** 131 * Return the file format of a given URL. 132 * @param url the URL to check 133 * @return the format of the URL 134 * @throws UnsupportedAudioFileException if the URL's format is not 135 * recognized 136 * @throws IOException if there is an I/O error reading the URL 137 */ 138 public static AudioFileFormat getAudioFileFormat(URL url) 139 throws UnsupportedAudioFileException, IOException 140 { 141 Iterator i = ServiceFactory.lookupProviders(AudioFileReader.class); 142 while (i.hasNext()) 143 { 144 AudioFileReader reader = (AudioFileReader) i.next(); 145 try 146 { 147 return reader.getAudioFileFormat(url); 148 } 149 catch (UnsupportedAudioFileException _) 150 { 151 // Try the next provider. 152 } 153 } 154 throw new UnsupportedAudioFileException("URL type not recognized"); 155 } 156 157 /** 158 * Return an array of all the supported AudioFileFormat types. 159 * @return an array of unique types 160 */ 161 public static AudioFileFormat.Type[] getAudioFileTypes() 162 { 163 HashSet<AudioFileFormat.Type> result 164 = new HashSet<AudioFileFormat.Type>(); 165 Iterator i = ServiceFactory.lookupProviders(AudioFileWriter.class); 166 while (i.hasNext()) 167 { 168 AudioFileWriter writer = (AudioFileWriter) i.next(); 169 AudioFileFormat.Type[] types = writer.getAudioFileTypes(); 170 for (int j = 0; j < types.length; ++j) 171 result.add(types[j]); 172 } 173 return result.toArray(new AudioFileFormat.Type[result.size()]); 174 } 175 176 /** 177 * Return an array of all the supported AudioFileFormat types which match the 178 * given audio input stream 179 * @param ais the audio input stream 180 * @return an array of unique types 181 */ 182 public static AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream ais) 183 { 184 HashSet<AudioFileFormat.Type> result 185 = new HashSet<AudioFileFormat.Type>(); 186 Iterator i = ServiceFactory.lookupProviders(AudioFileWriter.class); 187 while (i.hasNext()) 188 { 189 AudioFileWriter writer = (AudioFileWriter) i.next(); 190 AudioFileFormat.Type[] types = writer.getAudioFileTypes(ais); 191 for (int j = 0; j < types.length; ++j) 192 result.add(types[j]); 193 } 194 return result.toArray(new AudioFileFormat.Type[result.size()]); 195 } 196 197 /** 198 * Given an audio input stream, this will try to create a new audio input 199 * stream whose encoding matches the given target encoding. If no provider 200 * offers this conversion, an exception is thrown. 201 * @param targ the target encoding 202 * @param ais the original audio stream 203 * @return a new audio stream 204 * @throws IllegalArgumentException if the conversion cannot be made 205 */ 206 public static AudioInputStream getAudioInputStream(AudioFormat.Encoding targ, 207 AudioInputStream ais) 208 { 209 Iterator i = ServiceFactory.lookupProviders(FormatConversionProvider.class); 210 while (i.hasNext()) 211 { 212 FormatConversionProvider prov = (FormatConversionProvider) i.next(); 213 if (! prov.isConversionSupported(targ, ais.getFormat())) 214 continue; 215 return prov.getAudioInputStream(targ, ais); 216 } 217 throw new IllegalArgumentException("encoding not supported for stream"); 218 } 219 220 /** 221 * Given an audio input stream, this will try to create a new audio input 222 * stream whose format matches the given target format. If no provider 223 * offers this conversion, an exception is thrown. 224 * @param targ the target format 225 * @param ais the original audio stream 226 * @return a new audio stream 227 * @throws IllegalArgumentException if the conversion cannot be made 228 */ 229 public static AudioInputStream getAudioInputStream(AudioFormat targ, 230 AudioInputStream ais) 231 { 232 Iterator i = ServiceFactory.lookupProviders(FormatConversionProvider.class); 233 while (i.hasNext()) 234 { 235 FormatConversionProvider prov = (FormatConversionProvider) i.next(); 236 if (! prov.isConversionSupported(targ, ais.getFormat())) 237 continue; 238 return prov.getAudioInputStream(targ, ais); 239 } 240 throw new IllegalArgumentException("format not supported for stream"); 241 } 242 243 /** 244 * Return an audio input stream for the file. 245 * @param f the file to read 246 * @return an audio input stream for the file 247 * @throws UnsupportedAudioFileException if the file's audio format is not 248 * recognized 249 * @throws IOException if there is an error while reading the file 250 */ 251 public static AudioInputStream getAudioInputStream(File f) 252 throws UnsupportedAudioFileException, IOException 253 { 254 Iterator i = ServiceFactory.lookupProviders(AudioFileReader.class); 255 while (i.hasNext()) 256 { 257 AudioFileReader reader = (AudioFileReader) i.next(); 258 try 259 { 260 return reader.getAudioInputStream(f); 261 } 262 catch (UnsupportedAudioFileException _) 263 { 264 // Try the next provider. 265 } 266 } 267 throw new UnsupportedAudioFileException("file type not recognized"); 268 } 269 270 /** 271 * Return an audio input stream given an input stream. 272 * @param is the input stream 273 * @return an audio input stream 274 * @throws UnsupportedAudioFileException if the input stream's audio format 275 * is not supported by any of the installed providers 276 * @throws IOException if there is an error while reading the input stream 277 */ 278 public static AudioInputStream getAudioInputStream(InputStream is) 279 throws UnsupportedAudioFileException, IOException 280 { 281 Iterator i = ServiceFactory.lookupProviders(AudioFileReader.class); 282 while (i.hasNext()) 283 { 284 AudioFileReader reader = (AudioFileReader) i.next(); 285 try 286 { 287 return reader.getAudioInputStream(is); 288 } 289 catch (UnsupportedAudioFileException _) 290 { 291 // Try the next provider. 292 } 293 } 294 throw new UnsupportedAudioFileException("input stream type not recognized"); 295 } 296 297 /** 298 * Return an audio input stream for the given URL. 299 * @param url the URL 300 * @return an audio input stream 301 * @throws UnsupportedAudioFileException if the URL's audio format is not 302 * supported by any of the installed providers 303 * @throws IOException if there is an error while reading the URL 304 */ 305 public static AudioInputStream getAudioInputStream(URL url) 306 throws UnsupportedAudioFileException, IOException 307 { 308 Iterator i = ServiceFactory.lookupProviders(AudioFileReader.class); 309 while (i.hasNext()) 310 { 311 AudioFileReader reader = (AudioFileReader) i.next(); 312 try 313 { 314 return reader.getAudioInputStream(url); 315 } 316 catch (UnsupportedAudioFileException _) 317 { 318 // Try the next provider. 319 } 320 } 321 throw new UnsupportedAudioFileException("URL type not recognized"); 322 } 323 324 /** 325 * Return a new clip which can be used for playing back an audio stream. 326 * @throws LineUnavailableException if a clip is not available for some 327 * reason 328 * @throws SecurityException if a clip cannot be made for security reasons 329 * @since 1.5 330 */ 331 public static Clip getClip() 332 throws LineUnavailableException 333 { 334 Mixer.Info[] infos = getMixerInfo(); 335 for (int i = 0; i < infos.length; ++i) 336 { 337 Mixer mix = getMixer(infos[i]); 338 Line[] lines = mix.getSourceLines(); 339 for (int j = 0; j < lines.length; ++j) 340 { 341 if (lines[j] instanceof Clip) 342 return (Clip) lines[j]; 343 } 344 } 345 throw new LineUnavailableException("no Clip available"); 346 } 347 348 /** 349 * Return a new clip which can be used for playing back an audio stream. 350 * The clip is obtained from the indicated mixer. 351 * @param info the mixer to use 352 * @throws LineUnavailableException if a clip is not available for some 353 * reason 354 * @throws SecurityException if a clip cannot be made for security reasons 355 * @since 1.5 356 */ 357 public static Clip getClip(Mixer.Info info) 358 throws LineUnavailableException 359 { 360 Mixer mix = getMixer(info); 361 Line[] lines = mix.getSourceLines(); 362 for (int j = 0; j < lines.length; ++j) 363 { 364 if (lines[j] instanceof Clip) 365 return (Clip) lines[j]; 366 } 367 throw new LineUnavailableException("no Clip available"); 368 } 369 370 /** 371 * Return a line matching the provided description. All the providers 372 * on the system are searched for a matching line. 373 * @param info description of the line 374 * @return the matching line 375 * @throws LineUnavailableException if no provider supplies a matching line 376 */ 377 public static Line getLine(Line.Info info) throws LineUnavailableException 378 { 379 Mixer.Info[] infos = getMixerInfo(); 380 for (int i = 0; i < infos.length; ++i) 381 { 382 Mixer mix = getMixer(infos[i]); 383 try 384 { 385 return mix.getLine(info); 386 } 387 catch (LineUnavailableException _) 388 { 389 // Try the next provider. 390 } 391 } 392 throw new LineUnavailableException("no Clip available"); 393 } 394 395 /** 396 * Return a mixer matching the provided description. All the providers 397 * on the system are searched for a matching mixer. 398 * @param info description of the mixer 399 * @return the matching mixer 400 * @throws IllegalArgumentException if no provider supplies a matching mixer 401 */ 402 public static Mixer getMixer(Mixer.Info info) 403 { 404 Iterator i = ServiceFactory.lookupProviders(MixerProvider.class); 405 while (i.hasNext()) 406 { 407 MixerProvider prov = (MixerProvider) i.next(); 408 if (prov.isMixerSupported(info)) 409 return prov.getMixer(info); 410 } 411 throw new IllegalArgumentException("mixer not found"); 412 } 413 414 /** 415 * Return an array of descriptions of all the mixers provided on the system. 416 */ 417 public static Mixer.Info[] getMixerInfo() 418 { 419 HashSet<Mixer.Info> result = new HashSet<Mixer.Info>(); 420 Iterator i = ServiceFactory.lookupProviders(MixerProvider.class); 421 while (i.hasNext()) 422 { 423 MixerProvider prov = (MixerProvider) i.next(); 424 Mixer.Info[] is = prov.getMixerInfo(); 425 for (int j = 0; j < is.length; ++j) 426 result.add(is[j]); 427 } 428 return result.toArray(new Mixer.Info[result.size()]); 429 } 430 431 /** 432 * Return a source data line matching the given audio format. 433 * @param fmt the audio format 434 * @throws LineUnavailableException if no source data line matching 435 * this format is available 436 * @since 1.5 437 */ 438 public static SourceDataLine getSourceDataLine(AudioFormat fmt) 439 throws LineUnavailableException 440 { 441 DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt); 442 Mixer.Info[] mixers = getMixerInfo(); 443 for (int i = 0; i < mixers.length; ++i) 444 { 445 Mixer mix = getMixer(mixers[i]); 446 if (mix.isLineSupported(info)) 447 return (SourceDataLine) mix.getLine(info); 448 } 449 throw new LineUnavailableException("source data line not found"); 450 } 451 452 /** 453 * Return a target data line matching the given audio format. 454 * @param fmt the audio format 455 * @throws LineUnavailableException if no target data line matching 456 * this format is available 457 * @since 1.5 458 */ 459 public static SourceDataLine getSourceDataLine(AudioFormat fmt, 460 Mixer.Info mixer) 461 throws LineUnavailableException 462 { 463 DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt); 464 Mixer mix = getMixer(mixer); 465 if (mix.isLineSupported(info)) 466 return (SourceDataLine) mix.getLine(info); 467 throw new LineUnavailableException("source data line not found"); 468 } 469 470 /** 471 * Return an array of descriptions of all the source lines matching 472 * the given line description. 473 * @param info description of the lines to match 474 */ 475 public static Line.Info[] getSourceLineInfo(Line.Info info) 476 { 477 HashSet<Line.Info> result = new HashSet<Line.Info>(); 478 Mixer.Info[] infos = getMixerInfo(); 479 for (int i = 0; i < infos.length; ++i) 480 { 481 Mixer mix = getMixer(infos[i]); 482 Line.Info[] srcs = mix.getSourceLineInfo(info); 483 for (int j = 0; j < srcs.length; ++j) 484 result.add(srcs[j]); 485 } 486 return result.toArray(new Line.Info[result.size()]); 487 } 488 489 /** 490 * Find and return a target data line matching the given audio format. 491 * @param fmt the format to match 492 * @throws LineUnavailableException if no matching line was found 493 * @since 1.5 494 */ 495 public static TargetDataLine getTargetDataLine(AudioFormat fmt) 496 throws LineUnavailableException 497 { 498 DataLine.Info info = new DataLine.Info(TargetDataLine.class, fmt); 499 Mixer.Info[] mixers = getMixerInfo(); 500 for (int i = 0; i < mixers.length; ++i) 501 { 502 Mixer mix = getMixer(mixers[i]); 503 if (mix.isLineSupported(info)) 504 return (TargetDataLine) mix.getLine(info); 505 } 506 throw new LineUnavailableException("target data line not found"); 507 } 508 509 /** 510 * Return a target data line matching the given audio format and 511 * mixer. 512 * @param fmt the audio format 513 * @param mixer the mixer description 514 * @return a target data line 515 * @throws LineUnavailableException if no matching target data line was 516 * found 517 * @since 1.5 518 */ 519 public static TargetDataLine getTargetDataLine(AudioFormat fmt, 520 Mixer.Info mixer) 521 throws LineUnavailableException 522 { 523 DataLine.Info info = new DataLine.Info(TargetDataLine.class, fmt); 524 Mixer mix = getMixer(mixer); 525 if (mix.isLineSupported(info)) 526 return (TargetDataLine) mix.getLine(info); 527 throw new LineUnavailableException("target data line not found"); 528 } 529 530 /** 531 * Given a source encoding, return an array of all target encodings to which 532 * data in this form can be converted. 533 * @param source the source encoding 534 */ 535 public static AudioFormat.Encoding[] getTargetEncodings(AudioFormat.Encoding source) 536 { 537 HashSet<AudioFormat.Encoding> result 538 = new HashSet<AudioFormat.Encoding>(); 539 Iterator i = ServiceFactory.lookupProviders(FormatConversionProvider.class); 540 while (i.hasNext()) 541 { 542 FormatConversionProvider prov = (FormatConversionProvider) i.next(); 543 if (! prov.isSourceEncodingSupported(source)) 544 continue; 545 AudioFormat.Encoding[] es = prov.getTargetEncodings(); 546 for (int j = 0; j < es.length; ++j) 547 result.add(es[j]); 548 } 549 return result.toArray(new AudioFormat.Encoding[result.size()]); 550 } 551 552 /** 553 * Given a source format, return an array of all the target encodings to 554 * which data in this format can be converted. 555 * @param source the source format 556 */ 557 public static AudioFormat.Encoding[] getTargetEncodings(AudioFormat source) 558 { 559 HashSet<AudioFormat.Encoding> result 560 = new HashSet<AudioFormat.Encoding>(); 561 Iterator i = ServiceFactory.lookupProviders(FormatConversionProvider.class); 562 while (i.hasNext()) 563 { 564 FormatConversionProvider prov = (FormatConversionProvider) i.next(); 565 AudioFormat.Encoding[] es = prov.getTargetEncodings(source); 566 for (int j = 0; j < es.length; ++j) 567 result.add(es[j]); 568 } 569 return result.toArray(new AudioFormat.Encoding[result.size()]); 570 } 571 572 /** 573 * Given a target encoding and a source audio format, return an array of all 574 * matching audio formats to which data in this source format can be converted. 575 * @param encoding the target encoding 576 * @param sourceFmt the source format 577 */ 578 public static AudioFormat[] getTargetFormats(AudioFormat.Encoding encoding, 579 AudioFormat sourceFmt) 580 { 581 HashSet<AudioFormat> result = new HashSet<AudioFormat>(); 582 Iterator i = ServiceFactory.lookupProviders(FormatConversionProvider.class); 583 while (i.hasNext()) 584 { 585 FormatConversionProvider prov = (FormatConversionProvider) i.next(); 586 AudioFormat[] es = prov.getTargetFormats(encoding, sourceFmt); 587 for (int j = 0; j < es.length; ++j) 588 result.add(es[j]); 589 } 590 return result.toArray(new AudioFormat[result.size()]); 591 } 592 593 /** 594 * Given a line description, return an array of descriptions of all 595 * the matching target lines. 596 * @param info the line description 597 */ 598 public static Line.Info[] getTargetLineInfo(Line.Info info) 599 { 600 HashSet<Line.Info> result = new HashSet<Line.Info>(); 601 Mixer.Info[] infos = getMixerInfo(); 602 for (int i = 0; i < infos.length; ++i) 603 { 604 Mixer mix = getMixer(infos[i]); 605 Line.Info[] targs = mix.getTargetLineInfo(info); 606 for (int j = 0; j < targs.length; ++j) 607 result.add(targs[j]); 608 } 609 return result.toArray(new Line.Info[result.size()]); 610 } 611 612 /** 613 * Return true if the currently installed providers are able to 614 * convert data from the given source format to the given target encoding. 615 * @param targ the target encoding 616 * @param source the source format 617 */ 618 public static boolean isConversionSupported(AudioFormat.Encoding targ, 619 AudioFormat source) 620 { 621 Iterator i 622 = ServiceFactory.lookupProviders(FormatConversionProvider.class); 623 while (i.hasNext()) 624 { 625 FormatConversionProvider prov = (FormatConversionProvider) i.next(); 626 if (prov.isConversionSupported(targ, source)) 627 return true; 628 } 629 return false; 630 } 631 632 /** 633 * Return true if the currently installed providers are able to convert 634 * the given source format to the given target format. 635 * @param targ the target format 636 * @param source the source format 637 */ 638 public static boolean isConversionSupported(AudioFormat targ, 639 AudioFormat source) 640 { 641 Iterator i 642 = ServiceFactory.lookupProviders(FormatConversionProvider.class); 643 while (i.hasNext()) 644 { 645 FormatConversionProvider prov = (FormatConversionProvider) i.next(); 646 if (prov.isConversionSupported(targ, source)) 647 return true; 648 } 649 return false; 650 } 651 652 private static boolean isFileTypeSupported(AudioFileFormat.Type[] types, 653 AudioFileFormat.Type type) 654 { 655 for (int i = 0; i < types.length; ++i) 656 { 657 if (types[i].equals(type)) 658 return true; 659 } 660 return false; 661 } 662 663 /** 664 * Return true if the given audio file format is supported by one of 665 * the providers installed on the system. 666 * @param type the audio file format type 667 */ 668 public static boolean isFileTypeSupported(AudioFileFormat.Type type) 669 { 670 return isFileTypeSupported(getAudioFileTypes(), type); 671 } 672 673 /** 674 * Return true if the given audio file format is supported for the 675 * given audio input stream by one of the providers installed on the 676 * system. 677 * @param type the audio file format type 678 * @param ais the audio input stream 679 */ 680 public static boolean isFileTypeSupported(AudioFileFormat.Type type, 681 AudioInputStream ais) 682 { 683 return isFileTypeSupported(getAudioFileTypes(ais), type); 684 } 685 686 /** 687 * Return true if some provider on the system supplies a line 688 * matching the argument. 689 * @param info the line to match 690 */ 691 public static boolean isLineSupported(Line.Info info) 692 { 693 Mixer.Info[] infos = getMixerInfo(); 694 for (int i = 0; i < infos.length; ++i) 695 { 696 if (getMixer(infos[i]).isLineSupported(info)) 697 return true; 698 } 699 return false; 700 } 701 702 /** 703 * Write an audio input stream to the given file, using the specified 704 * audio file format. All the providers installed on the system will 705 * be searched to find one that supports this operation. 706 * @param ais the audio input stream to write 707 * @param type the desired audio file format type 708 * @param out the file to write to 709 * @return the number of bytes written 710 * @throws IOException if an I/O error occurs while writing 711 * @throws IllegalArgumentException if the file type is not supported 712 */ 713 public static int write(AudioInputStream ais, AudioFileFormat.Type type, 714 File out) 715 throws IOException 716 { 717 Iterator i = ServiceFactory.lookupProviders(AudioFileWriter.class); 718 while (i.hasNext()) 719 { 720 AudioFileWriter w = (AudioFileWriter) i.next(); 721 if (w.isFileTypeSupported(type, ais)) 722 return w.write(ais, type, out); 723 } 724 throw new IllegalArgumentException("file type not supported by system"); 725 } 726 727 /** 728 * Write an audio input stream to the given output stream, using the 729 * specified audio file format. All the providers installed on the 730 * system will be searched to find one that supports this operation. 731 * @param ais the audio input stream to write 732 * @param type the desired audio file format type 733 * @param os the output stream to write to 734 * @return the number of bytes written 735 * @throws IOException if an I/O error occurs while writing 736 * @throws IllegalArgumentException if the file type is not supported 737 */ 738 public static int write(AudioInputStream ais, AudioFileFormat.Type type, 739 OutputStream os) 740 throws IOException 741 { 742 Iterator i = ServiceFactory.lookupProviders(AudioFileWriter.class); 743 while (i.hasNext()) 744 { 745 AudioFileWriter w = (AudioFileWriter) i.next(); 746 if (w.isFileTypeSupported(type, ais)) 747 return w.write(ais, type, os); 748 } 749 throw new IllegalArgumentException("file type not supported by system"); 750 } 751}