/* * Copyright (c) 2008, 2009, 2010, 2011 Denis Tulskiy * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General 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 General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>. */ package com.tulskiy.musique.audio; import com.tulskiy.musique.audio.formats.uncompressed.PCMEncoder; import com.tulskiy.musique.playlist.Track; import com.tulskiy.musique.util.AudioMath; import javax.sound.sampled.AudioFormat; import static org.junit.Assert.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; /** * Author: Denis Tulskiy * Date: 15.07.2009 */ public class DecoderSeekTester { private Decoder decoder; private long totalSamples; private ByteBuffer refB; private static final int CASES_TO_TEST = 10; private int frameSize; public DecoderSeekTester(Track track, Decoder decoder) { this.decoder = decoder; assertNotNull("Decoder is null", decoder); assertTrue("Decoder returned an error", this.decoder.open(track)); totalSamples = track.getTrackData().getTotalSamples(); System.out.println("File: " + track.getTrackData().getLocation().getPath() + ", Total samples: " + totalSamples); } public void start() { try { frameSize = decoder.getAudioFormat().getFrameSize(); SeekTestBuffer ref = new SeekTestBuffer(); refB = ByteBuffer.allocate((int) (totalSamples * frameSize) + 10000); refB.position(0); ref.saveReference = true; ref.oFile = File.createTempFile(decoder.getClass().getCanonicalName(), null); checkSeek(ref, 0); ref.encoder.close(); System.out.println("Done first decoder pass. Samples decoded: " + ref.currentSample); // assertTrue(totalSamples >= ref.currentSample); // assertEquals(totalSamples, ref.currentSample); if (totalSamples != ref.currentSample) { System.out.println("Warning: decoded less samples than declared"); totalSamples = ref.currentSample; } SeekTestBuffer test = new SeekTestBuffer(); long[] testcase = new long[CASES_TO_TEST]; testcase[0] = 0; testcase[1] = 1; testcase[2] = totalSamples; for (int i = 4; i < CASES_TO_TEST; i++) testcase[i] = (int) (Math.random() * totalSamples); for (int i = 0; i < 10; i++) { long sample = testcase[i]; // int sample = (1152 * 5) + 576; // int sample = 12345; System.out.println("Seek to: " + sample); test.currentSample = 0; refB.rewind(); refB.position((int) (sample * frameSize)); try { // test.saveReference = true; // test.oFile = "testfiles/2.wav"; checkSeek(test, sample); // test.waveFile.Close(); assertEquals(totalSamples - sample, test.currentSample); System.err.println("Samples decoded: " + test.currentSample); // break; } catch (RuntimeException e) { e.printStackTrace(); System.out.println("Test failed: " + e.getMessage()); throw e; } } } catch (IOException e) { e.printStackTrace(); fail(); } finally { refB = null; decoder.close(); System.gc(); } } private void checkSeek(SeekTestBuffer b, long sample) { // decoder.setOutputStream(b); decoder.seekSample(sample); byte[] buffer = new byte[65536]; while (true) { int ret = decoder.decode(buffer); if (ret == -1) { break; } else { b.write(buffer, 0, ret); } } } private class SeekTestBuffer { int currentSample = 0; boolean saveReference = false; File oFile; private PCMEncoder encoder; @SuppressWarnings({"ResultOfMethodCallIgnored"}) public void write(byte[] b, int off, int len) { if (saveReference) { if (encoder == null) { encoder = new PCMEncoder(); encoder.open(oFile, new AudioFormat(44100f, 16, 2, true, false), null); oFile.deleteOnExit(); } encoder.encode(b, len); try { refB.put(b, off, len); } catch (BufferOverflowException e) { // e.printStackTrace(); return; } } else { refB.mark(); for (int i = off; i < off + len; i++) { if (refB.position() >= refB.limit()) { throw new RuntimeException("Too much samples decoded"); } byte bb = refB.get(); if (bb != b[i]) { try { FileOutputStream f1 = new FileOutputStream("tmp/frame1.dmp"); FileOutputStream f2 = new FileOutputStream("tmp/frame2.dmp"); refB.reset(); byte[] frame = new byte[len]; refB.get(frame); f1.write(frame); f2.write(b, off, len); f1.close(); f2.close(); } catch (IOException e) { e.printStackTrace(); } fail("Not equals " + refB.position()); } // assertEquals("Sample " + refB.position(), refB.get(), b[i]); } } currentSample += AudioMath.bytesToSamples(len, frameSize); } } }