/******************************************************************************
* *
* Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. *
* *
* COPYRIGHT: *
* This software is the property of Wimba S.A. *
* This software is redistributed under the Xiph.org variant of *
* the BSD license. *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* - Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* - Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* - Neither the name of Wimba, the Xiph.org Foundation nor the names of *
* its contributors may be used to endorse or promote products derived *
* from this software without specific prior written permission. *
* *
* WARRANTIES: *
* This software is made available by the authors in the hope *
* that it will be useful, but without any warranty. *
* Wimba S.A. is not liable for any consequence related to the *
* use of the provided software. *
* *
* Class: SpeexFormatConvertionProvider.java *
* *
* Author: Marc GIMPEL *
* *
* Date: 12th July 2003 *
* *
******************************************************************************/
/* $Id: SpeexFormatConvertionProvider.java,v 1.2 2004/10/21 16:21:58 mgimpel Exp $ */
package org.xiph.speex.spi;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.spi.FormatConversionProvider;
/**
* A format conversion provider provides format conversion services from one or
* more input formats to one or more output formats. Converters include codecs,
* which encode and/or decode audio data, as well as transcoders, etc.
* Format converters provide methods for determining what conversions are
* supported and for obtaining an audio stream from which converted data can be
* read.
*
* The source format represents the format of the incoming audio data, which
* will be converted.
*
* The target format represents the format of the processed, converted audio
* data. This is the format of the data that can be read from the stream
* returned by one of the getAudioInputStream methods.
*
* @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com)
* @version $Revision: 1.2 $
*/
public class SpeexFormatConvertionProvider
extends FormatConversionProvider
{
/** */
public static final AudioFormat.Encoding[] NO_ENCODING = {};
/** */
public static final AudioFormat.Encoding[] PCM_ENCODING =
{AudioFormat.Encoding.PCM_SIGNED};
/** */
public static final AudioFormat.Encoding[] SPEEX_ENCODING =
{SpeexEncoding.SPEEX};
/** */
public static final AudioFormat.Encoding[] BOTH_ENCODINGS =
{SpeexEncoding.SPEEX, AudioFormat.Encoding.PCM_SIGNED};
/** */
public static final AudioFormat[] NO_FORMAT = {};
/**
* Obtains the set of source format encodings from which format conversion
* services are provided by this provider.
* @return array of source format encodings.
* The array will always have a length of at least 1.
*/
public AudioFormat.Encoding[] getSourceEncodings()
{
AudioFormat.Encoding[] encodings = {SpeexEncoding.SPEEX,
AudioFormat.Encoding.PCM_SIGNED};
return encodings;
}
/**
* Obtains the set of target format encodings to which format conversion
* services are provided by this provider.
* @return array of target format encodings.
* The array will always have a length of at least 1.
*/
public AudioFormat.Encoding[] getTargetEncodings()
{
AudioFormat.Encoding[] encodings = {SpeexEncoding.SPEEX_Q0,
SpeexEncoding.SPEEX_Q1,
SpeexEncoding.SPEEX_Q2,
SpeexEncoding.SPEEX_Q3,
SpeexEncoding.SPEEX_Q4,
SpeexEncoding.SPEEX_Q5,
SpeexEncoding.SPEEX_Q6,
SpeexEncoding.SPEEX_Q7,
SpeexEncoding.SPEEX_Q8,
SpeexEncoding.SPEEX_Q9,
SpeexEncoding.SPEEX_Q10,
SpeexEncoding.SPEEX_VBR0,
SpeexEncoding.SPEEX_VBR1,
SpeexEncoding.SPEEX_VBR2,
SpeexEncoding.SPEEX_VBR3,
SpeexEncoding.SPEEX_VBR4,
SpeexEncoding.SPEEX_VBR5,
SpeexEncoding.SPEEX_VBR6,
SpeexEncoding.SPEEX_VBR7,
SpeexEncoding.SPEEX_VBR8,
SpeexEncoding.SPEEX_VBR9,
SpeexEncoding.SPEEX_VBR10,
AudioFormat.Encoding.PCM_SIGNED};
return encodings;
}
/**
* Obtains the set of target format encodings supported by the format
* converter given a particular source format. If no target format encodings
* are supported for this source format, an array of length 0 is returned.
* @param sourceFormat format of the incoming data.
* @return array of supported target format encodings.
*/
public AudioFormat.Encoding[] getTargetEncodings(final AudioFormat sourceFormat)
{
if (sourceFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)) {
AudioFormat.Encoding[] encodings = {SpeexEncoding.SPEEX_Q0,
SpeexEncoding.SPEEX_Q1,
SpeexEncoding.SPEEX_Q2,
SpeexEncoding.SPEEX_Q3,
SpeexEncoding.SPEEX_Q4,
SpeexEncoding.SPEEX_Q5,
SpeexEncoding.SPEEX_Q6,
SpeexEncoding.SPEEX_Q7,
SpeexEncoding.SPEEX_Q8,
SpeexEncoding.SPEEX_Q9,
SpeexEncoding.SPEEX_Q10,
SpeexEncoding.SPEEX_VBR0,
SpeexEncoding.SPEEX_VBR1,
SpeexEncoding.SPEEX_VBR2,
SpeexEncoding.SPEEX_VBR3,
SpeexEncoding.SPEEX_VBR4,
SpeexEncoding.SPEEX_VBR5,
SpeexEncoding.SPEEX_VBR6,
SpeexEncoding.SPEEX_VBR7,
SpeexEncoding.SPEEX_VBR8,
SpeexEncoding.SPEEX_VBR9,
SpeexEncoding.SPEEX_VBR10};
return encodings;
}
else if (sourceFormat.getEncoding() instanceof SpeexEncoding) {
AudioFormat.Encoding[] encodings = {AudioFormat.Encoding.PCM_SIGNED};
return encodings;
}
else {
AudioFormat.Encoding[] encodings = {};
return encodings;
}
}
/**
* Obtains the set of target formats with the encoding specified supported by
* the format converter. If no target formats with the specified encoding are
* supported for this source format, an array of length 0 is returned.
* @param targetEncoding desired encoding of the outgoing data.
* @param sourceFormat format of the incoming data.
* @return array of supported target formats.
*/
public AudioFormat[] getTargetFormats(final AudioFormat.Encoding targetEncoding,
final AudioFormat sourceFormat)
{
if (sourceFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED) &&
targetEncoding instanceof SpeexEncoding) {
if (sourceFormat.getChannels() > 2 || sourceFormat.getChannels() <= 0 ||
sourceFormat.isBigEndian()) {
AudioFormat[] formats = {};
return formats;
}
else {
AudioFormat[] formats = {new AudioFormat(targetEncoding,
sourceFormat.getSampleRate(),
-1, // sample size in bits
sourceFormat.getChannels(),
-1, // frame size
-1, // frame rate
false)}; // little endian
return formats;
}
}
else if (sourceFormat.getEncoding() instanceof SpeexEncoding &&
targetEncoding.equals(AudioFormat.Encoding.PCM_SIGNED)) {
AudioFormat[] formats = {new AudioFormat(sourceFormat.getSampleRate(),
16, // sample size in bits
sourceFormat.getChannels(),
true, // signed
false)}; // little endian (for PCM wav)
return formats;
}
else {
AudioFormat[] formats = {};
return formats;
}
}
/**
* Obtains an audio input stream with the specified encoding from the given
* audio input stream.
* @param targetEncoding - desired encoding of the stream after processing.
* @param sourceStream - stream from which data to be processed should be read.
* @return stream from which processed data with the specified target
* encoding may be read.
* @exception IllegalArgumentException - if the format combination supplied
* is not supported.
*/
public AudioInputStream getAudioInputStream(final AudioFormat.Encoding targetEncoding,
final AudioInputStream sourceStream)
{
if (isConversionSupported(targetEncoding, sourceStream.getFormat())) {
AudioFormat[] formats = getTargetFormats(targetEncoding,
sourceStream.getFormat());
if (formats != null && formats.length > 0) {
AudioFormat sourceFormat = sourceStream.getFormat();
AudioFormat targetFormat = formats[0];
if (sourceFormat.equals(targetFormat)) {
return sourceStream;
}
else if (sourceFormat.getEncoding() instanceof SpeexEncoding &&
targetFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)) {
return new Speex2PcmAudioInputStream(sourceStream, targetFormat, -1);
}
else if (sourceFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED) &&
targetFormat.getEncoding() instanceof SpeexEncoding) {
return new Pcm2SpeexAudioInputStream(sourceStream, targetFormat, -1);
}
else {
throw new IllegalArgumentException("unable to convert " + sourceFormat.toString() +
" to " + targetFormat.toString());
}
}
else {
throw new IllegalArgumentException("target format not found");
}
}
else {
throw new IllegalArgumentException("conversion not supported");
}
}
/**
* Obtains an audio input stream with the specified format from the given
* audio input stream.
* @param targetFormat - desired data format of the stream after processing.
* @param sourceStream - stream from which data to be processed should be read.
* @return stream from which processed data with the specified format may be
* read.
* @exception IllegalArgumentException - if the format combination supplied
* is not supported.
*/
public AudioInputStream getAudioInputStream(final AudioFormat targetFormat,
final AudioInputStream sourceStream)
{
if (isConversionSupported(targetFormat, sourceStream.getFormat())) {
AudioFormat[] formats = getTargetFormats(targetFormat.getEncoding(),
sourceStream.getFormat());
if (formats != null && formats.length > 0) {
AudioFormat sourceFormat = sourceStream.getFormat();
if (sourceFormat.equals(targetFormat)) {
return sourceStream;
}
else if (sourceFormat.getEncoding() instanceof SpeexEncoding &&
targetFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)) {
return new Speex2PcmAudioInputStream(sourceStream, targetFormat, -1);
}
else if (sourceFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED) &&
targetFormat.getEncoding() instanceof SpeexEncoding) {
return new Pcm2SpeexAudioInputStream(sourceStream, targetFormat, -1);
}
else {
throw new IllegalArgumentException("unable to convert " + sourceFormat.toString() +
" to " + targetFormat.toString());
}
}
else {
throw new IllegalArgumentException("target format not found");
}
}
else {
throw new IllegalArgumentException("conversion not supported");
}
}
}