I would like to be able to investigate the available AudioFormat
types supported on a system with a view to selecting an appropriate one from a range of options, using preferred and fall-back values for frame rate and channels.
AudioSystem
doesn't support directly querying supported audio formats, but I can get a list of available SourceDataLine
from a Mixer
. And SourceDataLine
inherits a DataLine.Info
internal calls, which has a method to return the available formats: getFormats ()
.
So my primary question is: Is there a way to get an array of supported AudioFormat
objects out of the Java audio system?
Failing that: Is there a way to get an array of supported AudioFormat
objects out of a Mixer
?
And failing that: Is it possible to get a DataLine.Info
object from a SourceDataLine
?
Ideally, I would like to do something like the following:
public void exec () {
Mixer.Info [] mixerInfoList = AudioSystem.getMixerInfo ();
for (Mixer.Info mixerInfo : mixerInfoList) {
System.out.println (mixerInfo.getDescription ());
Mixer mixer = AudioSystem.getMixer (mixerInfo);
Line.Info [] lineInfoList = mixer.getSourceLineInfo ();
for (Line.Info rawLineInfo : lineInfoList) {
System.out.println (" " + rawLineInfo.toString ());
DataLine.Info lineInfo = (DataLine.Info) rawLineInfo;
AudioFormat [] formats = lineInfo.getFormats ();
for (AudioFormat fmt : formats) {
System.out.println (" " + fmt.toString ());
}
}
}
}
But this fails on the line DataLine.Info lineInfo = (DataLine.Info) rawLineInfo;
because rawLineInfo
is obviously an implementation-dependent object, not an instance of DataLineInfo
.
It really is tremendously disappointing that mixer.getSourceLineInfo ()
doesn't return an array of DataLine.Info
. There's no reason why it couldn't as the lines concerned are known with certainty to be implementations of SourceDataLine
and therefore must support an AudioFormat
.
Using the information provided by @gpasch (thanks heaps buddy) in the accepted answer, here's my final solution. Function isDesirable
identifies only audio formats I'm interested in. Class AudioFormatKey
is a wrapper that provides implementations of equals()
for the distinct()
transform, and compareTo()
for the sorted()
transform.
public void exec () {
System.out.println ("Available formats (stream):");
Arrays.stream (AudioSystem.getSourceLineInfo (new Line.Info (SourceDataLine.class)))
.filter (info -> info instanceof DataLine.Info)
.map (info -> (DataLine.Info) info)
.flatMap (dlinfo -> Arrays.stream (dlinfo.getFormats ()))
.filter (this::isDesirable)
.map (AudioFormatKey::new)
.distinct ()
.sorted ()
.map (AudioFormatKey::getFormat)
.forEach (format -> System.out.println (" " + format));
}
I have this thing - it gets a list of formats in Windows. I don't know if all are supported or they work but it gives a list.
public void getFormats() {
Line.Info desired = new Line.Info( SourceDataLine.class );
Line.Info[] info = AudioSystem.getSourceLineInfo( desired );
for ( int i = 0; i < info.length; ++i ) {
System.out.println(i+" "+info[i].toString());
if ( info[ i ] instanceof DataLine.Info ) {
AudioFormat[] forms = ((DataLine.Info) info[i]).getFormats();
for ( int n = 0; n < forms.length; ++n ) System.out.println( forms[ n ].toString() );
}
}
desired = new Line.Info( TargetDataLine.class );
info = AudioSystem.getTargetLineInfo( desired );
for ( int i = 0; i < info.length; ++i ) {
System.out.println(i+" "+info[i].toString());
if ( info[ i ] instanceof DataLine.Info ) {
AudioFormat[] forms = ((DataLine.Info) info[i]).getFormats();
for ( int n = 0; n < forms.length; ++n ) System.out.println( forms[ n ].toString() );
}
}
}