package net.sf.fmj.media.renderer.audio;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import javax.media.format.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
/**
* Utilities for dealing with JavaSound formats.
* @author Ken Larson
*
*/
public class JavaSoundUtils
{
public static boolean onlyStandardFormats = false;
// TODO: move remaining mpeg/vorbis code from JavaSoundCodec to here, make it work without those SPIs.
/**
* Convert javax.sound.sampled.AudioFormat to javax.media.format.AudioFormat.
*/
public static AudioFormat convertFormat(javax.sound.sampled.AudioFormat format) {
Encoding encoding = format.getEncoding();
int channels = format.getChannels();
float frameRate = format.getFrameRate();
int frameSize = format.getFrameSize() < 0 ? format.getFrameSize() : (format.getFrameSize() * 8);
float sampleRate = format.getSampleRate();
int sampleSize = format.getSampleSizeInBits();
int endian = format.isBigEndian() ? AudioFormat.BIG_ENDIAN : AudioFormat.LITTLE_ENDIAN;
int signed = AudioFormat.NOT_SPECIFIED;
String encodingString = AudioFormat.LINEAR;
if (encoding == Encoding.PCM_SIGNED) {
signed = AudioFormat.SIGNED;
encodingString = AudioFormat.LINEAR;
}
else if (encoding == Encoding.PCM_UNSIGNED) {
signed = AudioFormat.UNSIGNED;
encodingString = AudioFormat.LINEAR;
}
else if (encoding == Encoding.ALAW) {
encodingString = AudioFormat.ALAW;
}
else if (encoding == Encoding.ULAW) {
encodingString = AudioFormat.ULAW;
}
else {
encodingString = encoding.toString();
}
AudioFormat jmfFormat = new AudioFormat(
encodingString,
sampleRate,
sampleSize,
channels,
endian,
signed,
frameSize,
frameRate,
AudioFormat.byteArray
);
return jmfFormat;
}
/**
*
* @return null if doesn't match any mpeg encoding
*/
private static Encoding toMpegEncoding(String encodingStr)
{
try
{
if ( !JavaSoundUtils.onlyStandardFormats )
{
// mgodehardt: now using reflection
Class classMpegEncoding = Class.forName("javazoom.spi.mpeg.sampled.file.MpegEncoding");
final String[] mpegEncodingStrings = {"MPEG1L1", "MPEG1L2", "MPEG1L3", "MPEG2DOT5L1", "MPEG2DOT5L2", "MPEG2DOT5L3", "MPEG2L1", "MPEG2L2", "MPEG2L3"};
final Encoding[] mpegEncodings = new Encoding[mpegEncodingStrings.length];
for (int i=0; i<mpegEncodings.length; i++)
{
Field aField = classMpegEncoding.getDeclaredField(mpegEncodingStrings[i]);
mpegEncodings[i] = (Encoding)aField.get(null);
}
for (int i=0; i<mpegEncodings.length; ++i)
{
if ( encodingStr.equals(mpegEncodings[i].toString()) )
{
return mpegEncodings[i];
}
}
}
}
catch ( Exception dontcare )
{
}
return null;
}
/**
*
* @return null if doesn't match any vorbis encoding
*/
private static Encoding toVorbisEncoding(String encodingStr)
{
try
{
if ( !JavaSoundUtils.onlyStandardFormats )
{
// mgodehardt: now using reflection
Class classVorbisEncoding = Class.forName("javazoom.spi.vorbis.sampled.file.VorbisEncoding");
final String[] vorbisEncodingStrings = {"VORBISENC"};
final Encoding[] vorbisEncodings = new Encoding[vorbisEncodingStrings.length];
for (int i=0; i<vorbisEncodings.length; i++)
{
Field aField = classVorbisEncoding.getDeclaredField(vorbisEncodingStrings[i]);
vorbisEncodings[i] = (Encoding)aField.get(null);
}
for (int i=0; i<vorbisEncodings.length; ++i)
{
if ( encodingStr.equals(vorbisEncodings[i].toString()) )
{
return vorbisEncodings[i];
}
}
}
}
catch ( Exception dontcare )
{
}
return null;
}
public static javax.sound.sampled.AudioFormat convertFormat(AudioFormat format) {
String encodingString = format.getEncoding();
int channels = format.getChannels();
double frameRate = format.getFrameRate();
int frameSize = format.getFrameSizeInBits() / 8;
double sampleRate = format.getSampleRate();
int sampleSize = format.getSampleSizeInBits();
if (sampleSize > 8 && format.getEndian() == AudioFormat.NOT_SPECIFIED)
throw new IllegalArgumentException("Endianness must be specified");
boolean endian = (format.getEndian() == AudioFormat.BIG_ENDIAN);
int signed = format.getSigned();
Encoding encoding;
if (AudioFormat.LINEAR.equals(encodingString)) {
switch(signed) {
case AudioFormat.SIGNED:
encoding = Encoding.PCM_SIGNED;
break;
case AudioFormat.UNSIGNED:
encoding = Encoding.PCM_UNSIGNED;
break;
default:
throw new IllegalArgumentException("Signed/Unsigned must be specified");
//encoding = Encoding.PCM_SIGNED; // TODO: return null
}
}
else if (AudioFormat.ALAW.equals(encodingString)) {
encoding = Encoding.ALAW;
}
else if (AudioFormat.ULAW.equals(encodingString)) {
encoding = Encoding.ULAW;
}
else if (toMpegEncoding(encodingString) != null) {
encoding = toMpegEncoding(encodingString);
}
else if (toVorbisEncoding(encodingString) != null) {
encoding = toVorbisEncoding(encodingString);
}
else {
encoding = new CustomEncoding(encodingString);
}
javax.sound.sampled.AudioFormat sampledFormat;
Class classMpegEncoding = null;
Class classVorbisEncoding = null;
if ( !JavaSoundUtils.onlyStandardFormats )
{
try
{
classMpegEncoding = Class.forName("javazoom.spi.mpeg.sampled.file.MpegEncoding");
classVorbisEncoding = Class.forName("javazoom.spi.vorbis.sampled.file.VorbisEncoding");
}
catch ( Exception dontcare )
{
}
}
if (encoding == Encoding.PCM_SIGNED) {
sampledFormat = new javax.sound.sampled.AudioFormat(
(float)sampleRate,
sampleSize,
channels,
true,
endian
);
}
else if (encoding == Encoding.PCM_UNSIGNED) {
sampledFormat = new javax.sound.sampled.AudioFormat(
(float)sampleRate,
sampleSize,
channels,
false,
endian
);
}
else if ( (null != classMpegEncoding) && classMpegEncoding.isInstance(encoding) )
{
try
{
Class classMpegAudioFormat = Class.forName("javazoom.spi.mpeg.sampled.file.MpegAudioFormat");
Class partypes[] = new Class[8];
partypes[0] = javax.sound.sampled.AudioFormat.Encoding.class;
partypes[1] = Float.TYPE;
partypes[2] = Integer.TYPE;
partypes[3] = Integer.TYPE;
partypes[4] = Integer.TYPE;
partypes[5] = Float.TYPE;
partypes[6] = Boolean.TYPE;
partypes[7] = java.util.Map.class;
Constructor ct = classMpegAudioFormat.getConstructor(partypes);
Object arglist[] = new Object[8];
arglist[0] = encoding;
arglist[1] = (float)sampleRate;
arglist[2] = sampleSize;
arglist[3] = channels;
arglist[4] = frameSize;
arglist[5] = (float)frameRate;
arglist[6] = endian;
arglist[7] = new HashMap();
sampledFormat = (javax.sound.sampled.AudioFormat)ct.newInstance(arglist);
}
catch ( Exception dontcare )
{
sampledFormat = null;
}
}
else if ( (null != classVorbisEncoding) && classVorbisEncoding.isInstance(encoding) )
{
try
{
Class classVorbisAudioFormat = Class.forName("javazoom.spi.vorbis.sampled.file.VorbisAudioFormat");
Class partypes[] = new Class[8];
partypes[0] = javax.sound.sampled.AudioFormat.Encoding.class;
partypes[1] = Float.TYPE;
partypes[2] = Integer.TYPE;
partypes[3] = Integer.TYPE;
partypes[4] = Integer.TYPE;
partypes[5] = Float.TYPE;
partypes[6] = Boolean.TYPE;
partypes[7] = java.util.Map.class;
Constructor ct = classVorbisAudioFormat.getConstructor(partypes);
Object arglist[] = new Object[8];
arglist[0] = encoding;
arglist[1] = (float)sampleRate;
arglist[2] = sampleSize;
arglist[3] = channels;
arglist[4] = frameSize;
arglist[5] = (float)frameRate;
arglist[6] = endian;
arglist[7] = new HashMap();
sampledFormat = (javax.sound.sampled.AudioFormat)ct.newInstance(arglist);
}
catch ( Exception dontcare )
{
sampledFormat = null;
}
}
else
{
sampledFormat = new javax.sound.sampled.AudioFormat(
encoding,
(float)sampleRate,
sampleSize,
channels,
frameSize,
(float)frameRate,
endian
);
}
return sampledFormat;
}
}