/**
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kc7bfi.jflac.sound.spi;
import java.io.ByteArrayInputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import org.junit.Ignore;
/**
*
*/
/**
* Test the Java Sound SPI of the JFLAC decoder for consistency.
* <p>
* Usage: run this class. On error, it prints TEST FAILED as last output and
* returns an exit code of 1. If everything is OK, it prints TEST OK as last
* line and returns an exit code of 0. You need to have the root directory of
* the workspace containing the META-INF directory in the classpath, or the full
* jar in the classpath.
*
* @author Florian Bomers
*/
@Ignore("Not a JUnit Test class")
public class TestJavaSoundSPI {
private static boolean isSameBitsChannelSampleRate(final AudioFormat af1,
final AudioFormat af2) {
return (af1.getSampleSizeInBits() == af2.getSampleSizeInBits())
&& (af1.getChannels() == af2.getChannels())
&& (af1.getSampleRate() == af2.getSampleRate());
}
/**
* @param neg if true, then not being able to convert yields a successful
* test
* @return true if test succeeded
*/
private static boolean checkConversion(final AudioFormat srcFormat,
AudioFormat targetFormat, final boolean neg) {
final AudioInputStream srcStream = new AudioInputStream(
new ByteArrayInputStream(new byte[0]), srcFormat, -1);
boolean couldConvert = true;
try {
final AudioInputStream targetStream = AudioSystem.getAudioInputStream(
targetFormat, srcStream);
// always a failure if src bits != target bits, or src channels !=
// target channels
targetFormat = targetStream.getFormat();
if (!isSameBitsChannelSampleRate(srcFormat, targetFormat)) {
System.out.println("ERROR");
System.out.println(" converted stream has "
+ targetFormat.getChannels() + " channels, "
+ targetFormat.getSampleSizeInBits() + " bits, and "
+ targetFormat.getSampleRate() + "Hz, "
+ " but source stream had " + srcFormat.getChannels()
+ " channels, " + srcFormat.getSampleSizeInBits()
+ " bits, and " + srcFormat.getSampleRate() + "Hz");
return false;
}
} catch (final Exception e) {
couldConvert = false;
}
if (couldConvert == neg) {
System.out.println("ERROR");
System.out.println(" can" + ((!couldConvert) ? "not" : "")
+ " convert from " + srcFormat + " to " + targetFormat);
return false;
}
System.out.println("OK");
return true;
}
private static boolean checkConversion(final AudioFormat srcFormat,
final AudioFormat.Encoding targetEncoding, final boolean neg) {
final AudioInputStream srcStream = new AudioInputStream(
new ByteArrayInputStream(new byte[0]), srcFormat, -1);
boolean couldConvert = true;
try {
final AudioInputStream targetStream = AudioSystem.getAudioInputStream(
targetEncoding, srcStream);
// always a failure if src bits != target bits, or src channels !=
// target channels
final AudioFormat targetFormat = targetStream.getFormat();
if (!isSameBitsChannelSampleRate(srcFormat, targetFormat)) {
System.out.println("ERROR");
System.out.println(" converted stream has "
+ targetFormat.getChannels() + " channels, "
+ targetFormat.getSampleSizeInBits() + " bits, and "
+ targetFormat.getSampleRate() + "Hz, "
+ " but source stream had " + srcFormat.getChannels()
+ " channels, " + srcFormat.getSampleSizeInBits()
+ " bits, and " + srcFormat.getSampleRate() + "Hz");
return false;
}
} catch (final Exception e) {
couldConvert = false;
}
if (couldConvert == neg) {
System.out.println("ERROR");
System.out.println(" can" + ((!couldConvert) ? "not" : "")
+ " convert from " + srcFormat + " to " + targetEncoding);
return false;
}
System.out.println("OK");
return true;
}
private static boolean checkDirect(final AudioFormat srcFormat, final boolean neg) {
final AudioFormat targetFormat = new AudioFormat(srcFormat.getSampleRate(),
srcFormat.getSampleSizeInBits(), srcFormat.getChannels(), true,
false);
return checkConversion(srcFormat, targetFormat, neg);
}
/**
* test that the decoder discovery works correctly. This test is an
* end-to-end test, i.e. it uses AudioSystem for decoder discovery.
*/
public static boolean testDecoder() {
boolean success = true;
try {
System.out.println("Positive tests that setting up a decoded stream works.");
final int[] bitsOK = {
8, 16, 24
};
for (int channel = 1; channel <= 2; channel++) {
for (int bit = 0; bit < bitsOK.length; bit++) {
final AudioFormat srcFormat = new AudioFormat(
org.kc7bfi.jflac.sound.spi.FlacEncoding.FLAC,
16000, bitsOK[bit], channel, -1, -1, false);
System.out.print("can convert 1: " + channel + "-channel, "
+ bitsOK[bit] + "-bit FLAC to PCM...");
if (!checkDirect(srcFormat, false)) {
success = false;
}
System.out.print("can convert 2: " + channel + "-channel, "
+ bitsOK[bit] + "-bit FLAC to PCM...");
if (!checkConversion(srcFormat,
AudioFormat.Encoding.PCM_SIGNED, false)) {
success = false;
}
}
}
System.out.println();
System.out.println("Negative tests that the decoder does not claim to be able to convert non-supported formats.");
final int[] bitsCorrupt = {
0, 4, 10, 20, 32
};
for (int channel = 2; channel <= 3; channel++) {
for (int bit = 0; bit < bitsCorrupt.length; bit++) {
final AudioFormat srcFormat = new AudioFormat(
org.kc7bfi.jflac.sound.spi.FlacEncoding.FLAC,
16000, bitsCorrupt[bit], channel, -1, -1, false);
System.out.print("cannot convert 1: " + channel
+ "-channel, " + bitsCorrupt[bit]
+ "-bit FLAC to PCM...");
if (!checkDirect(srcFormat, true)) {
success = false;
}
System.out.print("cannot convert 2: " + channel
+ "-channel, " + bitsCorrupt[bit]
+ "-bit FLAC to PCM...");
if (!checkConversion(srcFormat,
AudioFormat.Encoding.PCM_SIGNED, true)) {
success = false;
}
}
}
final int[] channelsCorrupt = {
0, 3, 5, 10
};
for (int i = 0; i < channelsCorrupt.length; i++) {
for (int bit = 16; bit < 40; bit += 16) {
final AudioFormat srcFormat = new AudioFormat(
org.kc7bfi.jflac.sound.spi.FlacEncoding.FLAC,
16000, bit, channelsCorrupt[i], -1, -1, false);
System.out.print("cannot convert 1: " + channelsCorrupt[i]
+ "-channel, " + bit + "-bit FLAC to PCM...");
if (!checkDirect(srcFormat, true)) {
success = false;
}
System.out.print("cannot convert 2: " + channelsCorrupt[i]
+ "-channel, " + bit + "-bit FLAC to PCM...");
if (!checkConversion(srcFormat,
AudioFormat.Encoding.PCM_SIGNED, true)) {
success = false;
}
}
}
System.out.println();
System.out.println("Negative tests that the decoder does not claim to be able to convert bits, sample rate, or channels");
final float[] sampleRatesOK = {
16000, 22050, 44100, 96000
};
for (int srcChannel = 1; srcChannel <= 2; srcChannel++) {
for (int targetChannel = 1; targetChannel <= 2; targetChannel++) {
for (int srcBitIndex = 0; srcBitIndex < bitsOK.length; srcBitIndex++) {
for (int targetBitIndex = 0; targetBitIndex < bitsOK.length; targetBitIndex++) {
for (int srcSampleRateIndex = 0; srcSampleRateIndex < sampleRatesOK.length; srcSampleRateIndex++) {
for (int targetSampleRateIndex = 0; targetSampleRateIndex < sampleRatesOK.length; targetSampleRateIndex++) {
final int srcBit = bitsOK[srcBitIndex];
final int targetBit = bitsOK[targetBitIndex];
final float srcSampleRate = sampleRatesOK[srcSampleRateIndex];
final float targetSampleRate = sampleRatesOK[targetSampleRateIndex];
if ((srcBit != targetBit)
|| (srcChannel != targetChannel)
|| (srcSampleRate != targetSampleRate)) {
// OK, at least one combination of
// src/target parameters is not the same
final AudioFormat srcFormat = new AudioFormat(
org.kc7bfi.jflac.sound.spi.FlacEncoding.FLAC,
srcSampleRate, srcBit,
srcChannel, -1, -1, false);
final AudioFormat targetFormat = new AudioFormat(
targetSampleRate, targetBit,
targetChannel, true, false);
System.out.print("cannot convert: "
+ srcChannel + "-channel, "
+ srcBit + "-bit, "
+ srcSampleRate + "Hz FLAC to "
+ targetChannel + "-channel, "
+ targetBit + "-bit, "
+ targetSampleRate
+ "Hz PCM...");
if (!checkConversion(srcFormat,
targetFormat, true)) {
success = false;
}
}
}
}
}
}
}
}
System.out.println();
System.out.println("Negative tests that the decoder does not claim to be able to decode to big endian");
for (int srcChannel = 1; srcChannel <= 2; srcChannel++) {
for (int srcBitIndex = 0; srcBitIndex < bitsOK.length; srcBitIndex++) {
final int srcBit = bitsOK[srcBitIndex];
final float srcSampleRate = 22050;
final AudioFormat srcFormat = new AudioFormat(
org.kc7bfi.jflac.sound.spi.FlacEncoding.FLAC,
srcSampleRate, srcBit, srcChannel, -1, -1, false);
final AudioFormat targetFormat = new AudioFormat(srcSampleRate,
srcBit, srcChannel, true, true);
System.out.print("cannot convert: " + srcChannel
+ "-channel, " + srcBit + "-bit" + " FLAC to "
+ srcChannel + "-channel, " + srcBit + "-bit,"
+ " big-endian PCM...");
if (!checkConversion(srcFormat, targetFormat, true)) {
success = false;
}
}
}
} catch (final Throwable t) {
t.printStackTrace();
success = false;
}
return success;
}
public static boolean runTest() {
boolean success = true;
if (!testDecoder()) {
success = false;
}
return success;
}
public static void main(final String[] args) {
if (runTest()) {
System.out.println("TEST OK");
System.exit(0);
} else {
System.out.println("TEST FAILED");
System.exit(1);
}
}
}