diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..77431ec --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,24 @@ +# This workflow will build a Java project with Maven +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Java CI with Maven + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: macos-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build with Maven + run: mvn -B package --file pom.xml diff --git a/README.md b/README.md index 38cfe62..b41737a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Release](https://jitpack.io/v/umjammer/mp3spi.svg)](https://jitpack.io/#umjammer/mp3spi) [![Parent](https://img.shields.io/badge/Parent-vavi--sound--sandbox-pink)](https://github.com/umjammer/vavi-sound-sandbox) +[![Release](https://jitpack.io/v/umjammer/mp3spi.svg)](https://jitpack.io/#umjammer/mp3spi) [![Java CI with Maven](https://github.com/umjammer/mp3spi/workflows/Java%20CI%20with%20Maven/badge.svg)](https://github.com/umjammer/mp3spi/actions) [![Parent](https://img.shields.io/badge/Parent-vavi--sound--sandbox-pink)](https://github.com/umjammer/vavi-sound-sandbox) # MP3SPI @@ -16,8 +16,8 @@ MP3SPI is a SPI (Service Provider Interface) that adds MP3 support for JavaSound. It allows to play MPEG 1/2/2.5 Layer 1/2/3 files thanks to underlying JLayer -and Tritonus libraries. This is a non-commercial project and anyone can add his -contribution. MP3SPI is licensed under LGPL (see LICENSE.txt). +and Tritonus libraries. This is a non-commercial project and anyone can add his +contribution. MP3SPI is licensed under LGPL (see [LICENSE.txt](LICENSE.txt)). ## FAQ @@ -42,7 +42,7 @@ contribution. MP3SPI is licensed under LGPL (see LICENSE.txt). ### Does MP3SPI support VBR ? - Yes, It supports XING and VBRI VBR header too. + Yes, It supports XING and VBRI VBR header too. ### How to get ID3v2 tags from MP3SPI API ? @@ -64,17 +64,19 @@ contribution. MP3SPI is licensed under LGPL (see LICENSE.txt). Here are our benchmark notes : - * Heap use range : 1380KB to 1900KB - 370 classes loaded. + * Heap use range : 1380KB to 1900KB - 370 classes loaded. * Footprint : -| ~8MB |under WinNT4/Win2K + J2SE 1.3 (Hotspot) | +|memory|environment| |---|---| +| ~8MB |under WinNT4/Win2K + J2SE 1.3 (Hotspot) | | ~10MB |under WinNT4/Win2K + J2SE 1.4.1 (Hotspot) | * CPU usage : -| ~12%| under PIII 800Mhz/WinNT4+J2SE 1.3 (Hotspot) | +|cpu|environment| |---|---| +| ~12%| under PIII 800Mhz/WinNT4+J2SE 1.3 (Hotspot) | | ~8% | under PIII 1Ghz/Win2K+J2SE 1.3.1 (Hotspot) | | ~12% | under PIII 1Ghz/Win2K+J2SE 1.4.1 (Hotspot) | | ~1% | under PIII 1Ghz/Win2K+J2SE 1.5.0 (Hotspot) | @@ -91,10 +93,12 @@ contribution. MP3SPI is licensed under LGPL (see LICENSE.txt). ## KNOWN PROBLEMS -99% of MP3 plays well with JLayer but some (1%) return an `ArrayIndexOutOfBoundsException` -while playing. It might come from invalid audio frames. +99% of MP3 plays well with JLayer but some (1%) return an `ArrayIndexOutOfBoundsException` +while playing. It might come from invalid audio frames. + +When source is not a file, this cannot deal id3v1 tag which file size is larger than 20M bytes. ### Workaround -Just `try`/`catch` `ArrayIndexOutOfBoundsException` in your code to skip +Just `try`/`catch` `ArrayIndexOutOfBoundsException` in your code to skip non-detected invalid frames. diff --git a/build.xml b/build.xml deleted file mode 100644 index ee70b0f..0000000 --- a/build.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pom.xml b/pom.xml index 3b7a6e7..bc2e395 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,12 @@ net.javazoom mp3spi - 1.9.6 + 1.9.7 + + + com.github.umjammer.tritonus + 0.3.8 + @@ -17,14 +22,11 @@ maven-surefire-plugin - 2.22.0 - - - org.junit.platform - junit-platform-surefire-provider - 1.1.0 - - + 3.0.0-M4 + + -Djava.util.logging.config.file=${project.build.testOutputDirectory}/logging.properties + false + @@ -38,14 +40,14 @@ - com.github.umjammer.tritonus + ${tritonus.groupId} tritonus-share - 0.3.7-SNAPSHOT + ${tritonus.version} - com.github.umjammer.tritonus + ${tritonus.groupId} tritonus-remaining - 0.3.7-SNAPSHOT + ${tritonus.version} com.github.umjammer diff --git a/src/main/java/javazoom/spi/mpeg/sampled/file/MpegAudioFileReader.java b/src/main/java/javazoom/spi/mpeg/sampled/file/MpegAudioFileReader.java index 20c4229..339a842 100644 --- a/src/main/java/javazoom/spi/mpeg/sampled/file/MpegAudioFileReader.java +++ b/src/main/java/javazoom/spi/mpeg/sampled/file/MpegAudioFileReader.java @@ -81,7 +81,7 @@ public class MpegAudioFileReader extends TAudioFileReader { MpegEncoding.MPEG2L1, MpegEncoding.MPEG2L2, MpegEncoding.MPEG2L3 }, { MpegEncoding.MPEG1L1, MpegEncoding.MPEG1L2, MpegEncoding.MPEG1L3 }, { MpegEncoding.MPEG2DOT5L1, MpegEncoding.MPEG2DOT5L2, MpegEncoding.MPEG2DOT5L3 }, }; - public static final int INITAL_READ_LENGTH = 128000 * 4; // TODO a tag larger than this length causes an exception + public static final int INITAL_READ_LENGTH = 1024 * 1024 * 20; // TODO limitation private static final int MARK_LIMIT = INITAL_READ_LENGTH + 1; private static final String[] id3v1genres = { @@ -357,6 +357,7 @@ else if (((head[0] == 'O') | (head[0] == 'o')) && ((head[1] == 'G') | (head[1] = // MPEG header info. int nVersion = AudioSystem.NOT_SPECIFIED; int nLayer = AudioSystem.NOT_SPECIFIED; + @SuppressWarnings("unused") int nSFIndex = AudioSystem.NOT_SPECIFIED; int nMode = AudioSystem.NOT_SPECIFIED; int FrameSize = AudioSystem.NOT_SPECIFIED; @@ -373,7 +374,7 @@ else if (((head[0] == 'O') | (head[0] == 'o')) && ((head[1] == 'G') | (head[1] = try { Bitstream m_bitstream = new Bitstream(pis); - aff_properties.put("mp3.header.pos", new Integer(m_bitstream.header_pos())); + aff_properties.put("mp3.header.pos", m_bitstream.header_pos()); Header m_header = m_bitstream.readFrame(); // nVersion = 0 => MPEG2-LSF (Including MPEG2.5), nVersion = 1 => MPEG1 nVersion = m_header.version(); @@ -384,42 +385,42 @@ else if (((head[0] == 'O') | (head[0] == 'o')) && ((head[1] == 'G') | (head[1] = aff_properties.put("mp3.version.layer", Integer.toString(nLayer)); nSFIndex = m_header.sample_frequency(); nMode = m_header.mode(); - aff_properties.put("mp3.mode", new Integer(nMode)); + aff_properties.put("mp3.mode", nMode); nChannels = nMode == 3 ? 1 : 2; - aff_properties.put("mp3.channels", new Integer(nChannels)); + aff_properties.put("mp3.channels", nChannels); nVBR = m_header.vbr(); - af_properties.put("vbr", new Boolean(nVBR)); - aff_properties.put("mp3.vbr", new Boolean(nVBR)); - aff_properties.put("mp3.vbr.scale", new Integer(m_header.vbr_scale())); + af_properties.put("vbr", nVBR); + aff_properties.put("mp3.vbr", nVBR); + aff_properties.put("mp3.vbr.scale", m_header.vbr_scale()); FrameSize = m_header.calculate_framesize(); - aff_properties.put("mp3.framesize.bytes", new Integer(FrameSize)); + aff_properties.put("mp3.framesize.bytes", FrameSize); if (FrameSize < 0) throw new UnsupportedAudioFileException("Invalid FrameSize : " + FrameSize); nFrequency = m_header.frequency(); - aff_properties.put("mp3.frequency.hz", new Integer(nFrequency)); + aff_properties.put("mp3.frequency.hz", nFrequency); FrameRate = (float) ((1.0 / (m_header.ms_per_frame())) * 1000.0); - aff_properties.put("mp3.framerate.fps", new Float(FrameRate)); + aff_properties.put("mp3.framerate.fps", FrameRate); if (FrameRate < 0) throw new UnsupportedAudioFileException("Invalid FrameRate : " + FrameRate); if (mLength != AudioSystem.NOT_SPECIFIED) { - aff_properties.put("mp3.length.bytes", new Integer(mLength)); + aff_properties.put("mp3.length.bytes", mLength); nTotalFrames = m_header.max_number_of_frames(mLength); - aff_properties.put("mp3.length.frames", new Integer(nTotalFrames)); + aff_properties.put("mp3.length.frames", nTotalFrames); } BitRate = m_header.bitrate(); - af_properties.put("bitrate", new Integer(BitRate)); - aff_properties.put("mp3.bitrate.nominal.bps", new Integer(BitRate)); + af_properties.put("bitrate", BitRate); + aff_properties.put("mp3.bitrate.nominal.bps", BitRate); nHeader = m_header.getSyncHeader(); encoding = sm_aEncodings[nVersion][nLayer - 1]; aff_properties.put("mp3.version.encoding", encoding.toString()); if (mLength != AudioSystem.NOT_SPECIFIED) { nTotalMS = Math.round(m_header.total_ms(mLength)); - aff_properties.put("duration", new Long(nTotalMS * 1000L)); + aff_properties.put("duration", nTotalMS * 1000L); } - aff_properties.put("mp3.copyright", new Boolean(m_header.copyright())); - aff_properties.put("mp3.original", new Boolean(m_header.original())); - aff_properties.put("mp3.crc", new Boolean(m_header.checksums())); - aff_properties.put("mp3.padding", new Boolean(m_header.padding())); + aff_properties.put("mp3.copyright", m_header.copyright()); + aff_properties.put("mp3.original", m_header.original()); + aff_properties.put("mp3.crc", m_header.checksums()); + aff_properties.put("mp3.padding", m_header.padding()); InputStream id3v2 = m_bitstream.getRawID3v2(); if (id3v2 != null) { @@ -451,12 +452,33 @@ else if (((head[0] == 'O') | (head[0] == 'o')) && ((head[1] == 'G') | (head[1] = { FileInputStream fis = (FileInputStream) inputStream; byte[] id3v1 = new byte[128]; + @SuppressWarnings("unused") long bytesSkipped = fis.skip(inputStream.available() - id3v1.length); + @SuppressWarnings("unused") int read = fis.read(id3v1, 0, id3v1.length); if ((id3v1[0] == 'T') && (id3v1[1] == 'A') && (id3v1[2] == 'G')) { parseID3v1Frames(id3v1, aff_properties); } + } else { + if (TDebug.TraceAudioFileReader) TDebug.out("unknown size, maybe not a file: " + inputStream.available()); + if (inputStream.available() <= INITAL_READ_LENGTH) { + InputStream is = new BufferedInputStream(inputStream, inputStream.available()); + byte[] id3v1 = new byte[128]; + is.mark(inputStream.available()); + @SuppressWarnings("unused") + long bytesSkipped = is.skip(inputStream.available() - id3v1.length); + @SuppressWarnings("unused") + int read = is.read(id3v1, 0, id3v1.length); + // is.reset(); + if (TDebug.TraceAudioFileReader) TDebug.out((char) id3v1[0] + ", " + (char) id3v1[1] + ", " + (char) id3v1[2]); + if ((id3v1[0] == 'T') && (id3v1[1] == 'A') && (id3v1[2] == 'G')) + { + parseID3v1Frames(id3v1, aff_properties); + } + } else { + if (TDebug.TraceAudioFileReader) TDebug.out("larger than limit 20MB, skip id3v1"); + } } AudioFormat format = new MpegAudioFormat(encoding, nFrequency, AudioSystem.NOT_SPECIFIED // SampleSizeInBits - The size of a sample , nChannels // Channels - The number of channels @@ -565,6 +587,8 @@ public AudioInputStream getAudioInputStream(InputStream inputStream) throws Unsu { if (TDebug.TraceAudioFileReader) TDebug.out("MpegAudioFileReader.getAudioInputStream(InputStream inputStream)"); if (!inputStream.markSupported()) inputStream = new BufferedInputStream(inputStream); + if (TDebug.TraceAudioFileReader) TDebug.out("available/limit: " + inputStream.available() + ", " + getMarkLimit()); + setMarkLimit(Math.min(inputStream.available(), getMarkLimit())); return super.getAudioInputStream(inputStream); } @@ -610,6 +634,7 @@ protected void parseID3v1Frames(byte[] frames, Map props) * @param end * @return */ + @SuppressWarnings("unused") private String chopSubstring(String s, int start, int end) { String str = null; diff --git a/src/test/java/PlayerTest.java b/src/test/java/PlayerTest.java index e3f2b54..844d3d9 100644 --- a/src/test/java/PlayerTest.java +++ b/src/test/java/PlayerTest.java @@ -20,8 +20,8 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.PrintStream; import java.util.Properties; +import java.util.logging.Logger; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; @@ -34,6 +34,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -52,7 +53,7 @@ public class PlayerTest { private String filename = null; private String name = null; private Properties props = null; - private PrintStream out = null; + private Logger out; @BeforeEach protected void setUp() throws Exception { @@ -62,9 +63,10 @@ protected void setUp() throws Exception { basefile = props.getProperty("basefile"); name = props.getProperty("filename"); filename = basefile + name; - out = System.out; + out = Logger.getLogger(PlayerTest.class.getName()); } + @Test @Disabled public void testPlay0() throws Exception { AudioInputStream in = AudioSystem.getAudioInputStream(new File(filename)); @@ -80,45 +82,38 @@ public void testPlay0() throws Exception { rawplay(decodedFormat, din); } + @Test @Disabled - public void testPlay() { - try { + public void testPlay() throws Exception { + out.info("--- Start : " + filename + " ---"); + File file = new File(filename); + //URL file = new URL(props.getProperty("shoutcast")); + AudioFileFormat aff = AudioSystem.getAudioFileFormat(file); + out.info("Audio Type : " + aff.getType()); + AudioInputStream in = AudioSystem.getAudioInputStream(file); + AudioInputStream din = null; + if (in != null) { + AudioFormat baseFormat = in.getFormat(); + out.info("Source Format : " + baseFormat.toString()); + AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, + baseFormat.getSampleRate(), + 16, + baseFormat.getChannels(), + baseFormat.getChannels() * 2, + baseFormat.getSampleRate(), + false); if (out != null) - out.println("--- Start : " + filename + " ---"); - File file = new File(filename); - //URL file = new URL(props.getProperty("shoutcast")); - AudioFileFormat aff = AudioSystem.getAudioFileFormat(file); - if (out != null) - out.println("Audio Type : " + aff.getType()); - AudioInputStream in = AudioSystem.getAudioInputStream(file); - AudioInputStream din = null; - if (in != null) { - AudioFormat baseFormat = in.getFormat(); - if (out != null) - out.println("Source Format : " + baseFormat.toString()); - AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, - baseFormat.getSampleRate(), - 16, - baseFormat.getChannels(), - baseFormat.getChannels() * 2, - baseFormat.getSampleRate(), - false); - if (out != null) - out.println("Target Format : " + decodedFormat.toString()); - din = AudioSystem.getAudioInputStream(decodedFormat, in); - if (din instanceof PropertiesContainer) { - assertTrue(true, "PropertiesContainer : OK"); - } else { - assertTrue(false, "Wrong PropertiesContainer instance"); - } - rawplay(decodedFormat, din); - in.close(); - if (out != null) - out.println("--- Stop : " + filename + " ---"); - assertTrue(true, "testPlay : OK"); + out.info("Target Format : " + decodedFormat.toString()); + din = AudioSystem.getAudioInputStream(decodedFormat, in); + if (din instanceof PropertiesContainer) { + assertTrue(true, "PropertiesContainer : OK"); + } else { + assertTrue(false, "Wrong PropertiesContainer instance"); } - } catch (Exception e) { - assertTrue(false, "testPlay : " + e.getMessage()); + rawplay(decodedFormat, din); + in.close(); + out.info("--- Stop : " + filename + " ---"); + assertTrue(true, "testPlay : OK"); } } @@ -140,11 +135,11 @@ private void rawplay(AudioFormat targetFormat, AudioInputStream din) throws IOEx gainControl.setValue(dB); // Start line.start(); - int nBytesRead = 0, nBytesWritten = 0; + int nBytesRead = 0; while (nBytesRead != -1) { nBytesRead = din.read(data, 0, data.length); if (nBytesRead != -1) - nBytesWritten = line.write(data, 0, nBytesRead); + line.write(data, 0, nBytesRead); } // Stop line.drain(); diff --git a/src/test/java/Test3.java b/src/test/java/Test3.java index b80d80b..835e5c4 100644 --- a/src/test/java/Test3.java +++ b/src/test/java/Test3.java @@ -5,6 +5,14 @@ */ import java.io.File; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.concurrent.atomic.AtomicInteger; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; @@ -16,6 +24,7 @@ import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; /** @@ -24,11 +33,9 @@ * @author Naohide Sano (umjammer) * @version 0.00 2012/06/11 umjammer initial version
*/ -@Disabled -public class Test3 { +class Test3 { -// static final String inFile = "/Users/nsano/src/sano-n/vavi-util-tag-mp3spi/src/test/resources/test.mp3"; - static final String inFile = "/Users/nsano/Music/iTunes/iTunes Music/NAMCO/Ace Combat 04 Shattered Skies Original Sound Tracks/1-11 Blockade.mp3"; + static final String inFile = "src/test/resources/test.mp3"; /** * @param args @@ -78,6 +85,35 @@ public static void main(String[] args) throws Exception { line.drain(); line.close(); } + + @Test + @Disabled + void test() throws IOException { + Path root = Paths.get(System.getProperty("user.home"), "Music", "iTunes", "iTunes Music"); +System.err.println("ROOT: " + Files.exists(root)); + + AtomicInteger count = new AtomicInteger(); + AtomicInteger error = new AtomicInteger(); + Files.walkFileTree(root, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attr) { + if (file.getFileName().toString().toLowerCase().endsWith(".mp3")) { +//System.err.println(file); + count.incrementAndGet(); + try { + AudioSystem.getAudioInputStream(file.toFile()); + } catch (Exception e) { + try { +System.err.println("ERROR: " + file + ", " + Files.size(file)); + } catch (Exception f) {} + error.incrementAndGet(); + } + } + return FileVisitResult.CONTINUE; + } + }); +System.err.println("RESULT: " + error + "/" + count); + } } /* */ diff --git a/src/test/java/javazoom/spi/mpeg/sampled/file/PropertiesTest.java b/src/test/java/javazoom/spi/mpeg/sampled/file/PropertiesTest.java index cea9386..a33eee9 100644 --- a/src/test/java/javazoom/spi/mpeg/sampled/file/PropertiesTest.java +++ b/src/test/java/javazoom/spi/mpeg/sampled/file/PropertiesTest.java @@ -2,26 +2,25 @@ package javazoom.spi.mpeg.sampled.file; import java.io.File; -import java.io.IOException; import java.io.InputStream; -import java.io.PrintStream; import java.net.URL; import java.util.Iterator; import java.util.Map; import java.util.Properties; +import java.util.logging.Logger; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.UnsupportedAudioFileException; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.tritonus.share.sampled.TAudioFormat; import org.tritonus.share.sampled.file.TAudioFileFormat; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; /** @@ -30,7 +29,7 @@ * generate your own test.mp3.properties Uncomment out = System.out; in setUp() * method to generated it on stdout from your own MP3 file. */ -public class PropertiesTest { +class PropertiesTest { private String basefile = null; private String baseurl = null; @@ -38,227 +37,182 @@ public class PropertiesTest { private String fileurl = null; private String name = null; private Properties props = null; - private PrintStream out = null; + private Logger logger; @BeforeEach - protected void setUp() throws Exception { + void setUp() throws Exception { props = new Properties(); InputStream pin = getClass().getClassLoader().getResourceAsStream("test.mp3.properties"); props.load(pin); basefile = props.getProperty("basefile"); - baseurl = props.getProperty("baseurl"); + baseurl = props.getProperty("baseurl").replaceAll("\\$\\{PWD\\}", System.getProperty("user.dir")); name = props.getProperty("filename"); filename = basefile + name; fileurl = baseurl + name; - out = System.out; + logger = Logger.getLogger(PropertiesTest.class.getName()); } @Test - public void testPropertiesFile() { - String[] testPropsAFF = { + void testPropertiesFile() throws Exception { + final String[] testPropsAFF = { "duration", "title", "author", "album", "date", "comment", "copyright", "mp3.framerate.fps", "mp3.copyright", "mp3.padding", "mp3.original", "mp3.length.bytes", "mp3.frequency.hz", "mp3.length.frames", "mp3.mode", "mp3.channels", "mp3.version.mpeg", "mp3.framesize.bytes", "mp3.vbr.scale", "mp3.version.encoding", "mp3.header.pos", "mp3.version.layer", "mp3.crc" }; - String[] testPropsAF = { + final String[] testPropsAF = { "vbr", "bitrate" }; File file = new File(filename); - AudioFileFormat baseFileFormat = null; - AudioFormat baseFormat = null; - try { - baseFileFormat = AudioSystem.getAudioFileFormat(file); - baseFormat = baseFileFormat.getFormat(); - if (out != null) - out.println("-> Filename : " + filename + " <-"); - if (out != null) - out.println(baseFileFormat); - if (baseFileFormat instanceof TAudioFileFormat) { - Map properties = ((TAudioFileFormat) baseFileFormat).properties(); - if (out != null) - out.println(properties); - for (int i = 0; i < testPropsAFF.length; i++) { - String key = testPropsAFF[i]; - String val = null; - if (properties.get(key) != null) - val = (properties.get(key)).toString(); - if (out != null) - out.println(key + "='" + val + "'"); - String valexpected = props.getProperty(key); - assertEquals(key, valexpected, val); - } - } else { - assertTrue(false, "testPropertiesFile : TAudioFileFormat expected"); + AudioFileFormat baseFileFormat = AudioSystem.getAudioFileFormat(file); + AudioFormat baseFormat = baseFileFormat.getFormat(); + logger.info("-> Filename : " + filename + " <-"); + logger.info(baseFileFormat.toString()); + if (baseFileFormat instanceof TAudioFileFormat) { + Map properties = ((TAudioFileFormat) baseFileFormat).properties(); + logger.info(properties.toString()); + for (int i = 0; i < testPropsAFF.length; i++) { + String key = testPropsAFF[i]; + String val = null; + if (properties.get(key) != null) + val = (properties.get(key)).toString(); + logger.info(key + "='" + val + "'"); + String valexpected = props.getProperty(key); + assertEquals(valexpected, val, key); } + } else { + fail("testPropertiesFile : TAudioFileFormat expected"); + } - if (baseFormat instanceof TAudioFormat) { - Map properties = ((TAudioFormat) baseFormat).properties(); - for (int i = 0; i < testPropsAF.length; i++) { - String key = testPropsAF[i]; - String val = null; - if (properties.get(key) != null) - val = (properties.get(key)).toString(); - if (out != null) - out.println(key + "='" + val + "'"); - String valexpected = props.getProperty(key); - assertEquals(key, valexpected, val); - } - } else { - assertTrue(false, "testPropertiesFile : TAudioFormat expected"); + if (baseFormat instanceof TAudioFormat) { + Map properties = ((TAudioFormat) baseFormat).properties(); + for (int i = 0; i < testPropsAF.length; i++) { + String key = testPropsAF[i]; + String val = null; + if (properties.get(key) != null) + val = (properties.get(key)).toString(); + logger.info(key + "='" + val + "'"); + String valexpected = props.getProperty(key); + assertEquals(valexpected, val, key); } - } catch (UnsupportedAudioFileException e) { - assertTrue(false, "testPropertiesFile : " + e.getMessage()); - } catch (IOException e) { - assertTrue(false, "testPropertiesFile : " + e.getMessage()); + } else { + fail("testPropertiesFile : TAudioFormat expected"); } } @Test - public void testPropertiesURL() { - String[] testPropsAFF = { /* "duration", */ + void testPropertiesURL() throws Exception { + final String[] testPropsAFF = { /* "duration", */ "title", "author", "album", "date", "comment", "copyright", "mp3.framerate.fps", "mp3.copyright", "mp3.padding", "mp3.original", /* "mp3.length.bytes", */"mp3.frequency.hz", /* "mp3.length.frames", */"mp3.mode", "mp3.channels", "mp3.version.mpeg", "mp3.framesize.bytes", "mp3.vbr.scale", "mp3.version.encoding", "mp3.header.pos", "mp3.version.layer", "mp3.crc" }; - String[] testPropsAF = { + final String[] testPropsAF = { "vbr", "bitrate" }; - AudioFileFormat baseFileFormat = null; - AudioFormat baseFormat = null; - try { - URL url = new URL(fileurl); - baseFileFormat = AudioSystem.getAudioFileFormat(url); - baseFormat = baseFileFormat.getFormat(); - if (out != null) - out.println("-> URL : " + filename + " <-"); - if (out != null) - out.println(baseFileFormat); - if (baseFileFormat instanceof TAudioFileFormat) { - Map properties = ((TAudioFileFormat) baseFileFormat).properties(); - for (int i = 0; i < testPropsAFF.length; i++) { - String key = testPropsAFF[i]; - String val = null; - if (properties.get(key) != null) - val = (properties.get(key)).toString(); - if (out != null) - out.println(key + "='" + val + "'"); - String valexpected = props.getProperty(key); - assertEquals(key, valexpected, val); - } - } else { - assertTrue(false, "testPropertiesURL : TAudioFileFormat expected"); + URL url = new URL(fileurl); + AudioFileFormat baseFileFormat = AudioSystem.getAudioFileFormat(url); + AudioFormat baseFormat = baseFileFormat.getFormat(); + logger.info("-> URL : " + filename + " <-"); + logger.info(baseFileFormat.toString()); + if (baseFileFormat instanceof TAudioFileFormat) { + Map properties = ((TAudioFileFormat) baseFileFormat).properties(); + for (int i = 0; i < testPropsAFF.length; i++) { + String key = testPropsAFF[i]; + String val = null; + if (properties.get(key) != null) + val = (properties.get(key)).toString(); + logger.info(key + "='" + val + "'"); + String valexpected = props.getProperty(key); + assertEquals(valexpected, val, key); } - if (baseFormat instanceof TAudioFormat) { - Map properties = ((TAudioFormat) baseFormat).properties(); - for (int i = 0; i < testPropsAF.length; i++) { - String key = testPropsAF[i]; - String val = null; - if (properties.get(key) != null) - val = (properties.get(key)).toString(); - if (out != null) - out.println(key + "='" + val + "'"); - String valexpected = props.getProperty(key); - assertEquals(key, valexpected, val); - } - } else { - assertTrue(false, "testPropertiesURL : TAudioFormat expected"); + } else { + fail("testPropertiesURL : TAudioFileFormat expected"); + } + + if (baseFormat instanceof TAudioFormat) { + Map properties = ((TAudioFormat) baseFormat).properties(); + for (int i = 0; i < testPropsAF.length; i++) { + String key = testPropsAF[i]; + String val = null; + if (properties.get(key) != null) + val = (properties.get(key)).toString(); + logger.info(key + "='" + val + "'"); + String valexpected = props.getProperty(key); + assertEquals(valexpected, val, key); } - } catch (UnsupportedAudioFileException e) { - assertTrue(false, "testPropertiesURL : " + e.getMessage()); - } catch (IOException e) { - assertTrue(false, "testPropertiesURL : " + e.getMessage()); + } else { + fail("testPropertiesURL : TAudioFormat expected"); } } @Test - public void testPropertiesShoutcast() { - AudioFileFormat baseFileFormat = null; - AudioFormat baseFormat = null; + @Disabled + void testPropertiesShoutcast() throws Exception { String shoutURL = props.getProperty("shoutcast"); - try { - URL url = new URL(shoutURL); - baseFileFormat = AudioSystem.getAudioFileFormat(url); - baseFormat = baseFileFormat.getFormat(); - if (out != null) - out.println("-> URL : " + url.toString() + " <-"); - if (out != null) - out.println(baseFileFormat); - if (baseFileFormat instanceof TAudioFileFormat) { - Map properties = ((TAudioFileFormat) baseFileFormat).properties(); - Iterator it = properties.keySet().iterator(); - while (it.hasNext()) { - String key = (String) it.next(); - String val = null; - if (properties.get(key) != null) - val = (properties.get(key)).toString(); - if (out != null) - out.println(key + "='" + val + "'"); - } - } else { - assertTrue(false, "testPropertiesShoutcast : TAudioFileFormat expected"); + URL url = new URL(shoutURL); + AudioFileFormat baseFileFormat = AudioSystem.getAudioFileFormat(url); + AudioFormat baseFormat = baseFileFormat.getFormat(); + logger.info("-> URL : " + url.toString() + " <-"); + logger.info(baseFileFormat.toString()); + if (baseFileFormat instanceof TAudioFileFormat) { + Map properties = ((TAudioFileFormat) baseFileFormat).properties(); + Iterator it = properties.keySet().iterator(); + while (it.hasNext()) { + String key = (String) it.next(); + String val = null; + if (properties.get(key) != null) + val = (properties.get(key)).toString(); + logger.info(key + "='" + val + "'"); } - if (baseFormat instanceof TAudioFormat) { - Map properties = ((TAudioFormat) baseFormat).properties(); - Iterator it = properties.keySet().iterator(); - while (it.hasNext()) { - String key = (String) it.next(); - String val = null; - if (properties.get(key) != null) - val = (properties.get(key)).toString(); - if (out != null) - out.println(key + "='" + val + "'"); - } - } else { - assertTrue(false, "testPropertiesShoutcast : TAudioFormat expected"); + } else { + fail("testPropertiesShoutcast : TAudioFileFormat expected"); + } + + if (baseFormat instanceof TAudioFormat) { + Map properties = ((TAudioFormat) baseFormat).properties(); + Iterator it = properties.keySet().iterator(); + while (it.hasNext()) { + String key = (String) it.next(); + String val = null; + if (properties.get(key) != null) + val = (properties.get(key)).toString(); + logger.info(key + "='" + val + "'"); } - } catch (UnsupportedAudioFileException e) { - assertTrue(false, "testPropertiesShoutcast : " + e.getMessage()); - } catch (IOException e) { - assertTrue(false, "testPropertiesShoutcast : " + e.getMessage()); + } else { + fail("testPropertiesShoutcast : TAudioFormat expected"); } } - public void _testDumpPropertiesFile() { - File file = new File(filename); - AudioFileFormat baseFileFormat = null; - AudioFormat baseFormat = null; - try { - baseFileFormat = AudioSystem.getAudioFileFormat(file); - baseFormat = baseFileFormat.getFormat(); - if (out != null) - out.println("-> Filename : " + filename + " <-"); - if (baseFileFormat instanceof TAudioFileFormat) { - Map properties = ((TAudioFileFormat) baseFileFormat).properties(); - Iterator it = properties.keySet().iterator(); - while (it.hasNext()) { - String key = (String) it.next(); - String val = (properties.get(key)).toString(); - if (out != null) - out.println(key + "='" + val + "'"); - } - } else { - assertTrue(false, "testDumpPropertiesFile : TAudioFileFormat expected"); + void testDumpPropertiesURL() throws Exception { + URL file = new URL(fileurl); + AudioFileFormat baseFileFormat = AudioSystem.getAudioFileFormat(file); + AudioFormat baseFormat = baseFileFormat.getFormat(); + logger.info("-> Filename : " + filename + " <-"); + if (baseFileFormat instanceof TAudioFileFormat) { + Map properties = ((TAudioFileFormat) baseFileFormat).properties(); + Iterator it = properties.keySet().iterator(); + while (it.hasNext()) { + String key = (String) it.next(); + String val = (properties.get(key)).toString(); + logger.info(key + "='" + val + "'"); } + } else { + fail("testDumpPropertiesFile : TAudioFileFormat expected"); + } - if (baseFormat instanceof TAudioFormat) { - Map properties = ((TAudioFormat) baseFormat).properties(); - Iterator it = properties.keySet().iterator(); - while (it.hasNext()) { - String key = (String) it.next(); - String val = (properties.get(key)).toString(); - if (out != null) - out.println(key + "='" + val + "'"); - } - } else { - assertTrue(false, "testDumpPropertiesFile : TAudioFormat expected"); + if (baseFormat instanceof TAudioFormat) { + Map properties = ((TAudioFormat) baseFormat).properties(); + Iterator it = properties.keySet().iterator(); + while (it.hasNext()) { + String key = (String) it.next(); + String val = (properties.get(key)).toString(); + logger.info(key + "='" + val + "'"); } - } catch (UnsupportedAudioFileException e) { - assertTrue(false, "testDumpPropertiesFile : " + e.getMessage()); - } catch (IOException e) { - assertTrue(false, "testDumpPropertiesFile : " + e.getMessage()); + } else { + fail("testDumpPropertiesFile : TAudioFormat expected"); } } } diff --git a/src/test/java/javazoom/spi/mpeg/sampled/file/SkipTest.java b/src/test/java/javazoom/spi/mpeg/sampled/file/SkipTest.java index 755ac51..b3d62f0 100644 --- a/src/test/java/javazoom/spi/mpeg/sampled/file/SkipTest.java +++ b/src/test/java/javazoom/spi/mpeg/sampled/file/SkipTest.java @@ -22,10 +22,10 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.PrintStream; +import java.net.URL; import java.util.Properties; +import java.util.logging.Logger; -import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; @@ -43,17 +43,17 @@ /** * Skip bytes before playing. */ -public class SkipTest { +class SkipTest { private String basefile = null; private String baseurl = null; private String filename = null; private String fileurl = null; private String name = null; private Properties props = null; - private PrintStream out = null; + private Logger out; @BeforeEach - protected void setUp() throws Exception { + void setUp() throws Exception { props = new Properties(); InputStream pin = getClass().getClassLoader().getResourceAsStream("test.mp3.properties"); props.load(pin); @@ -62,45 +62,61 @@ protected void setUp() throws Exception { name = props.getProperty("filename"); filename = basefile + name; fileurl = baseurl + name; - out = System.out; + out = Logger.getLogger(SkipTest.class.getName()); } @Test - public void testSkipFile() { - if (out != null) - out.println("-> Filename : " + filename + " <-"); - try { - File file = new File(filename); - AudioFileFormat aff = AudioSystem.getAudioFileFormat(file); - AudioInputStream in = AudioSystem.getAudioInputStream(file); - AudioInputStream din = null; - AudioFormat baseFormat = in.getFormat(); - if (out != null) - out.println("Source Format : " + baseFormat.toString()); - AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, - baseFormat.getSampleRate(), - 16, - baseFormat.getChannels(), - baseFormat.getChannels() * 2, - baseFormat.getSampleRate(), - false); - if (out != null) - out.println("Target Format : " + decodedFormat.toString()); - din = AudioSystem.getAudioInputStream(decodedFormat, in); - long toSkip = file.length() / 2; - long skipped = skip(din, toSkip); - if (out != null) - out.println("Skip : " + skipped + "/" + toSkip + " (Total=" + file.length() + ")"); - if (out != null) - out.println("Start playing"); - rawplay(decodedFormat, din); - in.close(); - if (out != null) - out.println("Played"); - assertTrue(true, "testSkip : OK"); - } catch (Exception e) { - assertTrue(false, e.getMessage()); - } + void testSkipFile() throws Exception { + out.info("-> Filename : " + filename + " <-"); + File file = new File(filename); + AudioInputStream in = AudioSystem.getAudioInputStream(file); + AudioInputStream din = null; + AudioFormat baseFormat = in.getFormat(); + out.info("Source Format : " + baseFormat.toString()); + AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, + baseFormat.getSampleRate(), + 16, + baseFormat.getChannels(), + baseFormat.getChannels() * 2, + baseFormat.getSampleRate(), + false); + out.info("Target Format : " + decodedFormat.toString()); + din = AudioSystem.getAudioInputStream(decodedFormat, in); + long toSkip = file.length() * 19 / 20; + long skipped = skip(din, toSkip); + out.info("Skip : " + skipped + "/" + toSkip + " (Total=" + file.length() + ")"); + out.info("Start playing"); + rawplay(decodedFormat, din); + in.close(); + out.info("Played"); + assertTrue(true, "testSkip : OK"); + } + + @Test + void testSkipUrl() throws Exception { + out.info("-> URL : " + fileurl + " <-"); + URL url = new URL(fileurl); + AudioInputStream in = AudioSystem.getAudioInputStream(url); + AudioInputStream din = null; + AudioFormat baseFormat = in.getFormat(); + out.info("Source Format : " + baseFormat.toString()); + AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, + baseFormat.getSampleRate(), + 16, + baseFormat.getChannels(), + baseFormat.getChannels() * 2, + baseFormat.getSampleRate(), + false); + out.info("Target Format : " + decodedFormat.toString()); + din = AudioSystem.getAudioInputStream(decodedFormat, in); + long toSkip = in.available() * 19 / 20; + long skipped = skip(din, toSkip); + out.info("Skip : " + skipped + "/" + toSkip + " (Total=" + in.available() + ")"); + out.info("Start playing"); + rawplay(decodedFormat, din); + in.close(); + out.info("Played"); + assertTrue(true, "testSkip : OK"); } private long skip(AudioInputStream in, long bytes) throws IOException { @@ -134,11 +150,11 @@ private void rawplay(AudioFormat targetFormat, AudioInputStream din) throws IOEx gainControl.setValue(dB); // Start line.start(); - int nBytesRead = 0, nBytesWritten = 0; + int nBytesRead = 0; while (nBytesRead != -1) { nBytesRead = din.read(data, 0, data.length); if (nBytesRead != -1) - nBytesWritten = line.write(data, 0, nBytesRead); + line.write(data, 0, nBytesRead); } // Stop line.drain(); diff --git a/src/test/resources/logging.properties b/src/test/resources/logging.properties new file mode 100644 index 0000000..8aa6f3e --- /dev/null +++ b/src/test/resources/logging.properties @@ -0,0 +1,14 @@ +handlers=java.util.logging.ConsoleHandler +.level=INFO +# Limit the message that are printed on the console to INFO and above. +java.util.logging.ConsoleHandler.level=INFO +java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter +# %1:date/time %2:className and methodName %3logName %4:level %5:message %6:errormessage +java.util.logging.SimpleFormatter.format=%1$tY/%1$tm/%1$td %1$tH:%1$tM:%1$tS.%1$tL [%4$s] %5$s %6$s%n + +# HttpUrlConnection +#java.util.logging.ConsoleHandler.level=ALL +#sun.net.www.protocol.http.HttpURLConnection.level=ALL + +#java.util.logging.ConsoleHandler.formatter=vavi.util.logging.VaviFormatter +#java.util.logging.ConsoleHandler.formatter=vavi.util.logging.BetterFormatter diff --git a/src/test/resources/test.mp3 b/src/test/resources/test.mp3 index 5219130..a4e1f47 100644 Binary files a/src/test/resources/test.mp3 and b/src/test/resources/test.mp3 differ diff --git a/src/test/resources/test.mp3.properties b/src/test/resources/test.mp3.properties index 8e0ca84..286b5df 100644 --- a/src/test/resources/test.mp3.properties +++ b/src/test/resources/test.mp3.properties @@ -7,8 +7,8 @@ shoutcast96=http://64.236.34.97:80/stream/1003 shoutcast128=http://160.79.128.35:7012/ # AudioFileFormat and AudioFormat properties -ByteLength=8945229 -FrameLength=14289 +ByteLength=8945664 +FrameLength=14290 Type=MP3 SourceFormat=MPEG1L3 44100.0 Hz, unknown bits per sample, stereo, unknown frame size, 38.28125 frames/second, Channels=2 @@ -19,35 +19,35 @@ SampleSizeInBits=-1 Encoding=MPEG1L3 # AudioInputStream properties -Available=8945229 +Available=8945664 # Extented Normalized (JDK1.5) AudioFormat properties -vbr=true -bitrate=229000 +vbr=false +bitrate=192000 # Extented Normalized (JDK1.5) AudioFileFormat properties -duration=212167000 +duration=373290000 title=We author=Scer album=The Sta no Expe date=2003 comment=Test Comments ! -copyright=copy +#copyright=copy # Extented MP3 AudioFileFormat properties mp3.framerate.fps=38.28125 mp3.copyright=false mp3.padding=false mp3.original=false -mp3.length.bytes=8945229 +mp3.length.bytes=8945664 mp3.frequency.hz=44100 -mp3.length.frames=8122 -mp3.mode=1 +mp3.length.frames=14290 +mp3.mode=0 mp3.channels=2 mp3.version.mpeg=1 -mp3.framesize.bytes=413 -mp3.vbr.scale=78 +mp3.framesize.bytes=622 +mp3.vbr.scale=0 mp3.version.encoding=MPEG1L3 -mp3.header.pos=2150 +mp3.header.pos=374 mp3.version.layer=3 -mp3.crc=false +mp3.crc=true