618 lines
23 KiB
Java
618 lines
23 KiB
Java
/*
|
|
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation. Oracle designates this
|
|
* particular file as subject to the "Classpath" exception as provided
|
|
* by Oracle in the LICENSE file that accompanied this code.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
package com.sun.media.sound;
|
|
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
|
|
import javax.sound.sampled.AudioFormat;
|
|
import javax.sound.sampled.AudioInputStream;
|
|
import javax.sound.sampled.AudioSystem;
|
|
import javax.sound.sampled.AudioFormat.Encoding;
|
|
import javax.sound.sampled.spi.FormatConversionProvider;
|
|
|
|
/**
|
|
* This class is used to convert between 8,16,24,32 bit signed/unsigned
|
|
* big/litle endian fixed/floating stereo/mono/multi-channel audio streams and
|
|
* perform sample-rate conversion if needed.
|
|
*
|
|
* @author Karl Helgason
|
|
*/
|
|
public final class AudioFloatFormatConverter extends FormatConversionProvider {
|
|
|
|
private static class AudioFloatFormatConverterInputStream extends
|
|
InputStream {
|
|
private final AudioFloatConverter converter;
|
|
|
|
private final AudioFloatInputStream stream;
|
|
|
|
private float[] readfloatbuffer;
|
|
|
|
private final int fsize;
|
|
|
|
AudioFloatFormatConverterInputStream(AudioFormat targetFormat,
|
|
AudioFloatInputStream stream) {
|
|
this.stream = stream;
|
|
converter = AudioFloatConverter.getConverter(targetFormat);
|
|
fsize = ((targetFormat.getSampleSizeInBits() + 7) / 8);
|
|
}
|
|
|
|
public int read() throws IOException {
|
|
byte[] b = new byte[1];
|
|
int ret = read(b);
|
|
if (ret < 0)
|
|
return ret;
|
|
return b[0] & 0xFF;
|
|
}
|
|
|
|
public int read(byte[] b, int off, int len) throws IOException {
|
|
|
|
int flen = len / fsize;
|
|
if (readfloatbuffer == null || readfloatbuffer.length < flen)
|
|
readfloatbuffer = new float[flen];
|
|
int ret = stream.read(readfloatbuffer, 0, flen);
|
|
if (ret < 0)
|
|
return ret;
|
|
converter.toByteArray(readfloatbuffer, 0, ret, b, off);
|
|
return ret * fsize;
|
|
}
|
|
|
|
public int available() throws IOException {
|
|
int ret = stream.available();
|
|
if (ret < 0)
|
|
return ret;
|
|
return ret * fsize;
|
|
}
|
|
|
|
public void close() throws IOException {
|
|
stream.close();
|
|
}
|
|
|
|
public synchronized void mark(int readlimit) {
|
|
stream.mark(readlimit * fsize);
|
|
}
|
|
|
|
public boolean markSupported() {
|
|
return stream.markSupported();
|
|
}
|
|
|
|
public synchronized void reset() throws IOException {
|
|
stream.reset();
|
|
}
|
|
|
|
public long skip(long n) throws IOException {
|
|
long ret = stream.skip(n / fsize);
|
|
if (ret < 0)
|
|
return ret;
|
|
return ret * fsize;
|
|
}
|
|
|
|
}
|
|
|
|
private static class AudioFloatInputStreamChannelMixer extends
|
|
AudioFloatInputStream {
|
|
|
|
private final int targetChannels;
|
|
|
|
private final int sourceChannels;
|
|
|
|
private final AudioFloatInputStream ais;
|
|
|
|
private final AudioFormat targetFormat;
|
|
|
|
private float[] conversion_buffer;
|
|
|
|
AudioFloatInputStreamChannelMixer(AudioFloatInputStream ais,
|
|
int targetChannels) {
|
|
this.sourceChannels = ais.getFormat().getChannels();
|
|
this.targetChannels = targetChannels;
|
|
this.ais = ais;
|
|
AudioFormat format = ais.getFormat();
|
|
targetFormat = new AudioFormat(format.getEncoding(), format
|
|
.getSampleRate(), format.getSampleSizeInBits(),
|
|
targetChannels, (format.getFrameSize() / sourceChannels)
|
|
* targetChannels, format.getFrameRate(), format
|
|
.isBigEndian());
|
|
}
|
|
|
|
public int available() throws IOException {
|
|
return (ais.available() / sourceChannels) * targetChannels;
|
|
}
|
|
|
|
public void close() throws IOException {
|
|
ais.close();
|
|
}
|
|
|
|
public AudioFormat getFormat() {
|
|
return targetFormat;
|
|
}
|
|
|
|
public long getFrameLength() {
|
|
return ais.getFrameLength();
|
|
}
|
|
|
|
public void mark(int readlimit) {
|
|
ais.mark((readlimit / targetChannels) * sourceChannels);
|
|
}
|
|
|
|
public boolean markSupported() {
|
|
return ais.markSupported();
|
|
}
|
|
|
|
public int read(float[] b, int off, int len) throws IOException {
|
|
int len2 = (len / targetChannels) * sourceChannels;
|
|
if (conversion_buffer == null || conversion_buffer.length < len2)
|
|
conversion_buffer = new float[len2];
|
|
int ret = ais.read(conversion_buffer, 0, len2);
|
|
if (ret < 0)
|
|
return ret;
|
|
if (sourceChannels == 1) {
|
|
int cs = targetChannels;
|
|
for (int c = 0; c < targetChannels; c++) {
|
|
for (int i = 0, ix = off + c; i < len2; i++, ix += cs) {
|
|
b[ix] = conversion_buffer[i];
|
|
}
|
|
}
|
|
} else if (targetChannels == 1) {
|
|
int cs = sourceChannels;
|
|
for (int i = 0, ix = off; i < len2; i += cs, ix++) {
|
|
b[ix] = conversion_buffer[i];
|
|
}
|
|
for (int c = 1; c < sourceChannels; c++) {
|
|
for (int i = c, ix = off; i < len2; i += cs, ix++) {
|
|
b[ix] += conversion_buffer[i];
|
|
}
|
|
}
|
|
float vol = 1f / ((float) sourceChannels);
|
|
for (int i = 0, ix = off; i < len2; i += cs, ix++) {
|
|
b[ix] *= vol;
|
|
}
|
|
} else {
|
|
int minChannels = Math.min(sourceChannels, targetChannels);
|
|
int off_len = off + len;
|
|
int ct = targetChannels;
|
|
int cs = sourceChannels;
|
|
for (int c = 0; c < minChannels; c++) {
|
|
for (int i = off + c, ix = c; i < off_len; i += ct, ix += cs) {
|
|
b[i] = conversion_buffer[ix];
|
|
}
|
|
}
|
|
for (int c = minChannels; c < targetChannels; c++) {
|
|
for (int i = off + c; i < off_len; i += ct) {
|
|
b[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
return (ret / sourceChannels) * targetChannels;
|
|
}
|
|
|
|
public void reset() throws IOException {
|
|
ais.reset();
|
|
}
|
|
|
|
public long skip(long len) throws IOException {
|
|
long ret = ais.skip((len / targetChannels) * sourceChannels);
|
|
if (ret < 0)
|
|
return ret;
|
|
return (ret / sourceChannels) * targetChannels;
|
|
}
|
|
|
|
}
|
|
|
|
private static class AudioFloatInputStreamResampler extends
|
|
AudioFloatInputStream {
|
|
|
|
private final AudioFloatInputStream ais;
|
|
|
|
private final AudioFormat targetFormat;
|
|
|
|
private float[] skipbuffer;
|
|
|
|
private SoftAbstractResampler resampler;
|
|
|
|
private final float[] pitch = new float[1];
|
|
|
|
private final float[] ibuffer2;
|
|
|
|
private final float[][] ibuffer;
|
|
|
|
private float ibuffer_index = 0;
|
|
|
|
private int ibuffer_len = 0;
|
|
|
|
private final int nrofchannels;
|
|
|
|
private float[][] cbuffer;
|
|
|
|
private final int buffer_len = 512;
|
|
|
|
private final int pad;
|
|
|
|
private final int pad2;
|
|
|
|
private final float[] ix = new float[1];
|
|
|
|
private final int[] ox = new int[1];
|
|
|
|
private float[][] mark_ibuffer = null;
|
|
|
|
private float mark_ibuffer_index = 0;
|
|
|
|
private int mark_ibuffer_len = 0;
|
|
|
|
AudioFloatInputStreamResampler(AudioFloatInputStream ais,
|
|
AudioFormat format) {
|
|
this.ais = ais;
|
|
AudioFormat sourceFormat = ais.getFormat();
|
|
targetFormat = new AudioFormat(sourceFormat.getEncoding(), format
|
|
.getSampleRate(), sourceFormat.getSampleSizeInBits(),
|
|
sourceFormat.getChannels(), sourceFormat.getFrameSize(),
|
|
format.getSampleRate(), sourceFormat.isBigEndian());
|
|
nrofchannels = targetFormat.getChannels();
|
|
Object interpolation = format.getProperty("interpolation");
|
|
if (interpolation != null && (interpolation instanceof String)) {
|
|
String resamplerType = (String) interpolation;
|
|
if (resamplerType.equalsIgnoreCase("point"))
|
|
this.resampler = new SoftPointResampler();
|
|
if (resamplerType.equalsIgnoreCase("linear"))
|
|
this.resampler = new SoftLinearResampler2();
|
|
if (resamplerType.equalsIgnoreCase("linear1"))
|
|
this.resampler = new SoftLinearResampler();
|
|
if (resamplerType.equalsIgnoreCase("linear2"))
|
|
this.resampler = new SoftLinearResampler2();
|
|
if (resamplerType.equalsIgnoreCase("cubic"))
|
|
this.resampler = new SoftCubicResampler();
|
|
if (resamplerType.equalsIgnoreCase("lanczos"))
|
|
this.resampler = new SoftLanczosResampler();
|
|
if (resamplerType.equalsIgnoreCase("sinc"))
|
|
this.resampler = new SoftSincResampler();
|
|
}
|
|
if (resampler == null)
|
|
resampler = new SoftLinearResampler2(); // new
|
|
// SoftLinearResampler2();
|
|
pitch[0] = sourceFormat.getSampleRate() / format.getSampleRate();
|
|
pad = resampler.getPadding();
|
|
pad2 = pad * 2;
|
|
ibuffer = new float[nrofchannels][buffer_len + pad2];
|
|
ibuffer2 = new float[nrofchannels * buffer_len];
|
|
ibuffer_index = buffer_len + pad;
|
|
ibuffer_len = buffer_len;
|
|
}
|
|
|
|
public int available() throws IOException {
|
|
return 0;
|
|
}
|
|
|
|
public void close() throws IOException {
|
|
ais.close();
|
|
}
|
|
|
|
public AudioFormat getFormat() {
|
|
return targetFormat;
|
|
}
|
|
|
|
public long getFrameLength() {
|
|
return AudioSystem.NOT_SPECIFIED; // ais.getFrameLength();
|
|
}
|
|
|
|
public void mark(int readlimit) {
|
|
ais.mark((int) (readlimit * pitch[0]));
|
|
mark_ibuffer_index = ibuffer_index;
|
|
mark_ibuffer_len = ibuffer_len;
|
|
if (mark_ibuffer == null) {
|
|
mark_ibuffer = new float[ibuffer.length][ibuffer[0].length];
|
|
}
|
|
for (int c = 0; c < ibuffer.length; c++) {
|
|
float[] from = ibuffer[c];
|
|
float[] to = mark_ibuffer[c];
|
|
for (int i = 0; i < to.length; i++) {
|
|
to[i] = from[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean markSupported() {
|
|
return ais.markSupported();
|
|
}
|
|
|
|
private void readNextBuffer() throws IOException {
|
|
|
|
if (ibuffer_len == -1)
|
|
return;
|
|
|
|
for (int c = 0; c < nrofchannels; c++) {
|
|
float[] buff = ibuffer[c];
|
|
int buffer_len_pad = ibuffer_len + pad2;
|
|
for (int i = ibuffer_len, ix = 0; i < buffer_len_pad; i++, ix++) {
|
|
buff[ix] = buff[i];
|
|
}
|
|
}
|
|
|
|
ibuffer_index -= (ibuffer_len);
|
|
|
|
ibuffer_len = ais.read(ibuffer2);
|
|
if (ibuffer_len >= 0) {
|
|
while (ibuffer_len < ibuffer2.length) {
|
|
int ret = ais.read(ibuffer2, ibuffer_len, ibuffer2.length
|
|
- ibuffer_len);
|
|
if (ret == -1)
|
|
break;
|
|
ibuffer_len += ret;
|
|
}
|
|
Arrays.fill(ibuffer2, ibuffer_len, ibuffer2.length, 0);
|
|
ibuffer_len /= nrofchannels;
|
|
} else {
|
|
Arrays.fill(ibuffer2, 0, ibuffer2.length, 0);
|
|
}
|
|
|
|
int ibuffer2_len = ibuffer2.length;
|
|
for (int c = 0; c < nrofchannels; c++) {
|
|
float[] buff = ibuffer[c];
|
|
for (int i = c, ix = pad2; i < ibuffer2_len; i += nrofchannels, ix++) {
|
|
buff[ix] = ibuffer2[i];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public int read(float[] b, int off, int len) throws IOException {
|
|
|
|
if (cbuffer == null || cbuffer[0].length < len / nrofchannels) {
|
|
cbuffer = new float[nrofchannels][len / nrofchannels];
|
|
}
|
|
if (ibuffer_len == -1)
|
|
return -1;
|
|
if (len < 0)
|
|
return 0;
|
|
int offlen = off + len;
|
|
int remain = len / nrofchannels;
|
|
int destPos = 0;
|
|
int in_end = ibuffer_len;
|
|
while (remain > 0) {
|
|
if (ibuffer_len >= 0) {
|
|
if (ibuffer_index >= (ibuffer_len + pad))
|
|
readNextBuffer();
|
|
in_end = ibuffer_len + pad;
|
|
}
|
|
|
|
if (ibuffer_len < 0) {
|
|
in_end = pad2;
|
|
if (ibuffer_index >= in_end)
|
|
break;
|
|
}
|
|
|
|
if (ibuffer_index < 0)
|
|
break;
|
|
int preDestPos = destPos;
|
|
for (int c = 0; c < nrofchannels; c++) {
|
|
ix[0] = ibuffer_index;
|
|
ox[0] = destPos;
|
|
float[] buff = ibuffer[c];
|
|
resampler.interpolate(buff, ix, in_end, pitch, 0,
|
|
cbuffer[c], ox, len / nrofchannels);
|
|
}
|
|
ibuffer_index = ix[0];
|
|
destPos = ox[0];
|
|
remain -= destPos - preDestPos;
|
|
}
|
|
for (int c = 0; c < nrofchannels; c++) {
|
|
int ix = 0;
|
|
float[] buff = cbuffer[c];
|
|
for (int i = c + off; i < offlen; i += nrofchannels) {
|
|
b[i] = buff[ix++];
|
|
}
|
|
}
|
|
return len - remain * nrofchannels;
|
|
}
|
|
|
|
public void reset() throws IOException {
|
|
ais.reset();
|
|
if (mark_ibuffer == null)
|
|
return;
|
|
ibuffer_index = mark_ibuffer_index;
|
|
ibuffer_len = mark_ibuffer_len;
|
|
for (int c = 0; c < ibuffer.length; c++) {
|
|
float[] from = mark_ibuffer[c];
|
|
float[] to = ibuffer[c];
|
|
for (int i = 0; i < to.length; i++) {
|
|
to[i] = from[i];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public long skip(long len) throws IOException {
|
|
if (len < 0)
|
|
return 0;
|
|
if (skipbuffer == null)
|
|
skipbuffer = new float[1024 * targetFormat.getFrameSize()];
|
|
float[] l_skipbuffer = skipbuffer;
|
|
long remain = len;
|
|
while (remain > 0) {
|
|
int ret = read(l_skipbuffer, 0, (int) Math.min(remain,
|
|
skipbuffer.length));
|
|
if (ret < 0) {
|
|
if (remain == len)
|
|
return ret;
|
|
break;
|
|
}
|
|
remain -= ret;
|
|
}
|
|
return len - remain;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private final Encoding[] formats = {Encoding.PCM_SIGNED,
|
|
Encoding.PCM_UNSIGNED,
|
|
Encoding.PCM_FLOAT};
|
|
|
|
public AudioInputStream getAudioInputStream(Encoding targetEncoding,
|
|
AudioInputStream sourceStream) {
|
|
if (sourceStream.getFormat().getEncoding().equals(targetEncoding))
|
|
return sourceStream;
|
|
AudioFormat format = sourceStream.getFormat();
|
|
int channels = format.getChannels();
|
|
Encoding encoding = targetEncoding;
|
|
float samplerate = format.getSampleRate();
|
|
int bits = format.getSampleSizeInBits();
|
|
boolean bigendian = format.isBigEndian();
|
|
if (targetEncoding.equals(Encoding.PCM_FLOAT))
|
|
bits = 32;
|
|
AudioFormat targetFormat = new AudioFormat(encoding, samplerate, bits,
|
|
channels, channels * bits / 8, samplerate, bigendian);
|
|
return getAudioInputStream(targetFormat, sourceStream);
|
|
}
|
|
|
|
public AudioInputStream getAudioInputStream(AudioFormat targetFormat,
|
|
AudioInputStream sourceStream) {
|
|
if (!isConversionSupported(targetFormat, sourceStream.getFormat()))
|
|
throw new IllegalArgumentException("Unsupported conversion: "
|
|
+ sourceStream.getFormat().toString() + " to "
|
|
+ targetFormat.toString());
|
|
return getAudioInputStream(targetFormat, AudioFloatInputStream
|
|
.getInputStream(sourceStream));
|
|
}
|
|
|
|
public AudioInputStream getAudioInputStream(AudioFormat targetFormat,
|
|
AudioFloatInputStream sourceStream) {
|
|
|
|
if (!isConversionSupported(targetFormat, sourceStream.getFormat()))
|
|
throw new IllegalArgumentException("Unsupported conversion: "
|
|
+ sourceStream.getFormat().toString() + " to "
|
|
+ targetFormat.toString());
|
|
if (targetFormat.getChannels() != sourceStream.getFormat()
|
|
.getChannels())
|
|
sourceStream = new AudioFloatInputStreamChannelMixer(sourceStream,
|
|
targetFormat.getChannels());
|
|
if (Math.abs(targetFormat.getSampleRate()
|
|
- sourceStream.getFormat().getSampleRate()) > 0.000001)
|
|
sourceStream = new AudioFloatInputStreamResampler(sourceStream,
|
|
targetFormat);
|
|
return new AudioInputStream(new AudioFloatFormatConverterInputStream(
|
|
targetFormat, sourceStream), targetFormat, sourceStream
|
|
.getFrameLength());
|
|
}
|
|
|
|
public Encoding[] getSourceEncodings() {
|
|
return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
|
|
Encoding.PCM_FLOAT };
|
|
}
|
|
|
|
public Encoding[] getTargetEncodings() {
|
|
return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
|
|
Encoding.PCM_FLOAT };
|
|
}
|
|
|
|
public Encoding[] getTargetEncodings(AudioFormat sourceFormat) {
|
|
if (AudioFloatConverter.getConverter(sourceFormat) == null)
|
|
return new Encoding[0];
|
|
return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
|
|
Encoding.PCM_FLOAT };
|
|
}
|
|
|
|
public AudioFormat[] getTargetFormats(Encoding targetEncoding,
|
|
AudioFormat sourceFormat) {
|
|
if (AudioFloatConverter.getConverter(sourceFormat) == null)
|
|
return new AudioFormat[0];
|
|
int channels = sourceFormat.getChannels();
|
|
|
|
ArrayList<AudioFormat> formats = new ArrayList<AudioFormat>();
|
|
|
|
if (targetEncoding.equals(Encoding.PCM_SIGNED))
|
|
formats.add(new AudioFormat(Encoding.PCM_SIGNED,
|
|
AudioSystem.NOT_SPECIFIED, 8, channels, channels,
|
|
AudioSystem.NOT_SPECIFIED, false));
|
|
if (targetEncoding.equals(Encoding.PCM_UNSIGNED))
|
|
formats.add(new AudioFormat(Encoding.PCM_UNSIGNED,
|
|
AudioSystem.NOT_SPECIFIED, 8, channels, channels,
|
|
AudioSystem.NOT_SPECIFIED, false));
|
|
|
|
for (int bits = 16; bits < 32; bits += 8) {
|
|
if (targetEncoding.equals(Encoding.PCM_SIGNED)) {
|
|
formats.add(new AudioFormat(Encoding.PCM_SIGNED,
|
|
AudioSystem.NOT_SPECIFIED, bits, channels, channels
|
|
* bits / 8, AudioSystem.NOT_SPECIFIED, false));
|
|
formats.add(new AudioFormat(Encoding.PCM_SIGNED,
|
|
AudioSystem.NOT_SPECIFIED, bits, channels, channels
|
|
* bits / 8, AudioSystem.NOT_SPECIFIED, true));
|
|
}
|
|
if (targetEncoding.equals(Encoding.PCM_UNSIGNED)) {
|
|
formats.add(new AudioFormat(Encoding.PCM_UNSIGNED,
|
|
AudioSystem.NOT_SPECIFIED, bits, channels, channels
|
|
* bits / 8, AudioSystem.NOT_SPECIFIED, true));
|
|
formats.add(new AudioFormat(Encoding.PCM_UNSIGNED,
|
|
AudioSystem.NOT_SPECIFIED, bits, channels, channels
|
|
* bits / 8, AudioSystem.NOT_SPECIFIED, false));
|
|
}
|
|
}
|
|
|
|
if (targetEncoding.equals(Encoding.PCM_FLOAT)) {
|
|
formats.add(new AudioFormat(Encoding.PCM_FLOAT,
|
|
AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4,
|
|
AudioSystem.NOT_SPECIFIED, false));
|
|
formats.add(new AudioFormat(Encoding.PCM_FLOAT,
|
|
AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4,
|
|
AudioSystem.NOT_SPECIFIED, true));
|
|
formats.add(new AudioFormat(Encoding.PCM_FLOAT,
|
|
AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8,
|
|
AudioSystem.NOT_SPECIFIED, false));
|
|
formats.add(new AudioFormat(Encoding.PCM_FLOAT,
|
|
AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8,
|
|
AudioSystem.NOT_SPECIFIED, true));
|
|
}
|
|
|
|
return formats.toArray(new AudioFormat[formats.size()]);
|
|
}
|
|
|
|
public boolean isConversionSupported(AudioFormat targetFormat,
|
|
AudioFormat sourceFormat) {
|
|
if (AudioFloatConverter.getConverter(sourceFormat) == null)
|
|
return false;
|
|
if (AudioFloatConverter.getConverter(targetFormat) == null)
|
|
return false;
|
|
if (sourceFormat.getChannels() <= 0)
|
|
return false;
|
|
if (targetFormat.getChannels() <= 0)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
public boolean isConversionSupported(Encoding targetEncoding,
|
|
AudioFormat sourceFormat) {
|
|
if (AudioFloatConverter.getConverter(sourceFormat) == null)
|
|
return false;
|
|
for (int i = 0; i < formats.length; i++) {
|
|
if (targetEncoding.equals(formats[i]))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
}
|