Permalink
Browse files

fix stream playing, example SndPlayer, test case

  • Loading branch information...
wolfgangasdf committed Nov 6, 2016
1 parent 8acdacf commit 0df7fb4f2ae3e3694e5e9499ee92184149136c1d
View
@@ -2,3 +2,5 @@ target
.project
.classpath
.settings
.idea
*.iml
@@ -890,7 +890,7 @@ private void findFrameSync() throws IOException {
// If we know the total number of samples in the stream, stop if we've read that many.
// This will stop us, for example, from wasting time trying to sync on an ID3V1 tag.
if (streamInfo != null && (streamInfo.getTotalSamples() != 0)) {
if (streamInfo != null && (streamInfo.getTotalSamples() > 0)) {
if (samplesDecoded >= streamInfo.getTotalSamples()) {
//state = DECODER_END_OF_STREAM;
return;
@@ -75,7 +75,7 @@ public String toString() {
}
public String [] getCommentByName( String key ) {
if (key == null ) return null;
if (numComments == 0 || key == null) return null;
java.util.Vector sbuff = new java.util.Vector();
for( int i=0; i < comments.length; i++ ) {
String comment = comments[i].toString();
@@ -398,8 +398,11 @@ protected AudioInputStream getAudioInputStream(InputStream inputStream, int medi
//ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
SequenceInputStream sequenceInputStream = new SequenceInputStream(byteInStream, inputStream);
//return new AudioInputStream(sequenceInputStream, audioFileFormat
// .getFormat(), audioFileFormat.getFrameLength());
return new AudioInputStream(sequenceInputStream, audioFileFormat.getFormat(), audioFileFormat.getFrameLength());
AudioFormat format = audioFileFormat.getFormat();
int frameLength = medialength; // if frameSize not specified, use byte length, see AudioInputStream
if (!(format.getFrameSize() == AudioSystem.NOT_SPECIFIED || format.getFrameSize() <= 0))
frameLength = audioFileFormat.getFrameLength();
return new AudioInputStream(sequenceInputStream, format, frameLength);
}
}
@@ -324,7 +324,7 @@ public synchronized int read() throws IOException {
*/
public synchronized int read(byte[] b, int off, int len) throws IOException {
checkIfStillOpen();
int frameSize = (int) getFrameLength();
int frameSize = getFormat().getFrameSize();
int bytesRead = 0;
// can only read integral number of frames
len -= (len % frameSize);
@@ -394,7 +394,7 @@ public synchronized long skip(long n) throws IOException {
*/
public synchronized int available() throws IOException {
checkIfStillOpen();
if (buffer.getAvailable() < (int) getFrameLength()) {
if (buffer.getAvailable() < getFormat().getFrameSize()) {
fill();
}
return buffer.getAvailable();
@@ -97,9 +97,9 @@ public static void playAudioStream(AudioInputStream audioInputStream) {
AudioFormat newFormat = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
audioFormat.getSampleRate(),
16,
(audioFormat.getSampleSizeInBits() > 0) ? audioFormat.getSampleSizeInBits() : 16,
audioFormat.getChannels(),
audioFormat.getChannels() * 2,
(audioFormat.getSampleSizeInBits() > 0) ? audioFormat.getChannels() * audioFormat.getSampleSizeInBits() / 8 : audioFormat.getChannels() * 2,
audioFormat.getSampleRate(),
false);
System.out.println("Converting audio format to " + newFormat);
@@ -127,7 +127,7 @@ public static void playAudioStream(AudioInputStream audioInputStream) {
// Adjust the volume on the output line.
if (dataLine.isControlSupported(FloatControl.Type.MASTER_GAIN)) {
FloatControl volume = (FloatControl) dataLine.getControl(FloatControl.Type.MASTER_GAIN);
volume.setValue(100.0F);
volume.setValue(volume.getMaximum()/2);
}
// Allows the line to move data in and out to a port.
@@ -0,0 +1,172 @@
package org.jflac.apps;
import org.apache.commons.io.FileUtils;
import org.jflac.util.WavWriter;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import javax.sound.sampled.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Decodes FLAC files with the official decoder, then jFLAC and compare outputs
*
* @author nicolas+github@guillaumin.me
*
*/
@RunWith(Parameterized.class)
public class DecoderStreamComparisonTest {
/** System property to override the FLAC binary location */
private static final String SYSPROP_OVERRIDE_BINARY = "jflac.test.flac.binary";
/** Working folder for the test */
private static final File OUTDIR = new File("target/test-output/decoder-comparison-stream");
/** Official FLAC binary */
private static final File FLAC_BINARY = getFlacBinary();
/** Input FLAC file */
@Parameter
public File input;
@Parameters(name = "{index}: {0}")
public static Collection<Object[]> data() {
File[] files = new File("../jflac-codec/src/test/resources/testdata").listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".flac");
}
});
List<Object[]> out = new ArrayList<Object[]>();
for (File f : files) {
out.add(new Object[] { f });
}
return out;
}
@Before
public void before() throws IOException {
Assume.assumeNotNull(FLAC_BINARY);
OUTDIR.mkdirs();
FileUtils.cleanDirectory(OUTDIR);
}
@Test
public void test() throws Exception {
File flacOut = new File(OUTDIR, input.getName() + ".official.wav");
Assert.assertFalse(
"Officially decoded file " + flacOut.getAbsolutePath() + " should not exist prior to the test",
flacOut.exists());
String[] cmd = new String[] {
FLAC_BINARY.getAbsolutePath(),
"--output-name=" + flacOut.getAbsolutePath(),
"--decode", input.getAbsolutePath()
};
Assert.assertEquals("FLAC decoder exit code", 0, Runtime.getRuntime().exec(cmd).waitFor());
Assert.assertTrue("File should have been decoded by the official decoder", flacOut.exists());
File jFlacOut = new File(OUTDIR, input.getName() + ".jflac.wav");
Assert.assertFalse("jFLAC decoded file should not exist prior to the test", jFlacOut.exists());
RandomAccessFile randomAccessFile = new RandomAccessFile(jFlacOut, "rw");
WavWriter wavWriter = new WavWriter(randomAccessFile);
wavWriter.writeHeader();
new Decoder().decode(input.getAbsolutePath(), jFlacOut.getAbsolutePath());
File soundFile = input;
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(soundFile);
AudioFormat audioFormat = audioInputStream.getFormat();
if (audioFormat.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) {
AudioFormat newFormat = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
audioFormat.getSampleRate(),
(audioFormat.getSampleSizeInBits() > 0) ? audioFormat.getSampleSizeInBits() : 16,
audioFormat.getChannels(),
(audioFormat.getSampleSizeInBits() > 0) ? audioFormat.getChannels() * audioFormat.getSampleSizeInBits() / 8 : audioFormat.getChannels() * 2,
audioFormat.getSampleRate(),
false);
System.out.println("Converting audio format to " + newFormat);
AudioInputStream newStream = AudioSystem.getAudioInputStream(newFormat, audioInputStream);
audioFormat = newFormat;
audioInputStream = newStream;
}
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
Assert.assertTrue("Play.playAudioStream does not handle this type of audio on this system.", AudioSystem.isLineSupported(info));
SourceDataLine dataLine = (SourceDataLine) AudioSystem.getLine(info);
dataLine.open(audioFormat);
dataLine.start();
int bufferSize = (int) audioFormat.getSampleRate() * audioFormat.getFrameSize();
byte [] buffer = new byte[ bufferSize ];
int bytesRead = 0;
while (bytesRead >= 0) {
bytesRead = audioInputStream.read(buffer, 0, buffer.length);
if (bytesRead >= 0) {
// System.out.println("Play.playAudioStream bytes read=" + bytesRead +
// ", frame size=" + audioFormat.getFrameSize() + ", frames read=" + bytesRead / audioFormat.getFrameSize());
// Odd sized sounds throw an exception if we don't write the same amount.
randomAccessFile.write(buffer, 0, bytesRead);
}
} // while
dataLine.drain();
dataLine.close();
randomAccessFile.close();
Assert.assertTrue("jFLAC decoded file should have been decoded", jFlacOut.exists());
Assert.assertArrayEquals("Decoded files should be identical",
FileUtils.readFileToByteArray(flacOut),
FileUtils.readFileToByteArray(jFlacOut));
}
/**
* Attempt to locate the official FLAC binary either from a provided system
* property or by looking in the PATH environment variable.
*
* @return FLAC binary, or null if not found
*/
private static File getFlacBinary() {
String binaryOverride = System.getProperty(SYSPROP_OVERRIDE_BINARY);
if (binaryOverride != null && new File(binaryOverride).exists()) {
File binary = new File(binaryOverride);
System.out.println("Using provided FLAC binary: " + binary.getAbsolutePath());
return binary;
}
String ext = "";
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
ext = ".exe";
}
String path = System.getenv("PATH");
for (String s: path.split(File.pathSeparator)) {
File binary = new File(s, "flac" + ext);
if (binary.exists()) {
System.out.println("Found FLAC binary: " + binary.getAbsolutePath());
return binary;
}
}
System.out.println("Unable to locate FLAC binary. Ensure it's in your PATH, or set "
+ SYSPROP_OVERRIDE_BINARY + " (e.g. -D" + SYSPROP_OVERRIDE_BINARY + "=C:\\Path\\To\\flac.exe)");
return null;
}
}

0 comments on commit 0df7fb4

Please sign in to comment.