[added] MP3 music and sound support to gdx-audio.
[added] Simple test class.
<classpathentry excluding="**/.svn/*" kind="src" path="src"/>\r
<classpathentry combineaccessrules="false" kind="src" path="/gdx-backend-lwjgl"/>\r
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>\r
+ <classpathentry kind="lib" path="lib/jlayer-1.0.1-libgdx.jar"/>\r
<classpathentry kind="output" path="bin"/>\r
</classpath>\r
--- /dev/null
+\r
+package com.baglogic.gdx.audio;\r
+\r
+import javazoom.jl.decoder.Bitstream;\r
+import javazoom.jl.decoder.BitstreamException;\r
+import javazoom.jl.decoder.Header;\r
+import javazoom.jl.decoder.MP3Decoder;\r
+import javazoom.jl.decoder.OutputBuffer;\r
+\r
+import com.badlogic.gdx.files.FileHandle;\r
+import com.badlogic.gdx.utils.GdxRuntimeException;\r
+\r
+public class Mp3Music extends OpenALMusic {\r
+ private Bitstream bitstream;\r
+ private OutputBuffer outputBuffer;\r
+ private MP3Decoder decoder;\r
+\r
+ public Mp3Music (OpenALAudio audio, FileHandle file) {\r
+ super(audio, file);\r
+ }\r
+\r
+ protected int read (byte[] buffer) {\r
+ try {\r
+ boolean setup = bitstream == null;\r
+ if (setup) {\r
+ bitstream = new Bitstream(file.read());\r
+\r
+ outputBuffer = new OutputBuffer(2, false);\r
+\r
+ decoder = new MP3Decoder();\r
+ decoder.setOutputBuffer(outputBuffer);\r
+ }\r
+\r
+ int totalLength = 0;\r
+ int minRequiredLength = buffer.length - OutputBuffer.BUFFERSIZE * 2 - 1;\r
+ while (totalLength < minRequiredLength) {\r
+ Header header = bitstream.readFrame();\r
+ if (header == null) break;\r
+ if (setup) {\r
+ setup(outputBuffer.isStereo() ? 2 : 1, header.getSampleRate());\r
+ setup = false;\r
+ }\r
+ try {\r
+ decoder.decodeFrame(header, bitstream);\r
+ } catch (Exception ignored) {\r
+ // JLayer's decoder throws ArrayIndexOutOfBoundsException sometimes!?\r
+ }\r
+ bitstream.closeFrame();\r
+\r
+ int length = outputBuffer.reset();\r
+ System.arraycopy(outputBuffer.getBuffer(), 0, buffer, totalLength, length);\r
+ totalLength += length;\r
+ }\r
+ return totalLength;\r
+ } catch (Throwable ex) {\r
+ reset();\r
+ throw new GdxRuntimeException("Error reading audio data.", ex);\r
+ }\r
+ }\r
+\r
+ protected void reset () {\r
+ if (bitstream == null) return;\r
+ try {\r
+ bitstream.close();\r
+ } catch (BitstreamException ignored) {\r
+ }\r
+ bitstream = null;\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.baglogic.gdx.audio;\r
+\r
+import java.io.ByteArrayOutputStream;\r
+\r
+import javazoom.jl.decoder.Bitstream;\r
+import javazoom.jl.decoder.Header;\r
+import javazoom.jl.decoder.MP3Decoder;\r
+import javazoom.jl.decoder.OutputBuffer;\r
+\r
+import com.badlogic.gdx.files.FileHandle;\r
+import com.badlogic.gdx.utils.GdxRuntimeException;\r
+\r
+public class Mp3Sound extends OpenALSound {\r
+ public Mp3Sound (OpenALAudio audio, FileHandle file) {\r
+ super(audio);\r
+\r
+ ByteArrayOutputStream output = new ByteArrayOutputStream(4096);\r
+\r
+ Bitstream bitstream = new Bitstream(file.read());\r
+\r
+ OutputBuffer outputBuffer = new OutputBuffer(2, false);\r
+\r
+ MP3Decoder decoder = new MP3Decoder();\r
+ decoder.setOutputBuffer(outputBuffer);\r
+\r
+ try {\r
+ int sampleRate = -1;\r
+ while (true) {\r
+ Header header = bitstream.readFrame();\r
+ if (header == null) break;\r
+ if (sampleRate == -1) sampleRate = header.getSampleRate();\r
+ try {\r
+ decoder.decodeFrame(header, bitstream);\r
+ } catch (Exception ignored) {\r
+ // JLayer's decoder throws ArrayIndexOutOfBoundsException sometimes!?\r
+ }\r
+ bitstream.closeFrame();\r
+ output.write(outputBuffer.getBuffer(), 0, outputBuffer.reset());\r
+ }\r
+ bitstream.close();\r
+ setup(output.toByteArray(), outputBuffer.isStereo() ? 2 : 1, sampleRate);\r
+ } catch (Throwable ex) {\r
+ throw new GdxRuntimeException("Error reading audio data.", ex);\r
+ }\r
+ }\r
+}\r
\r
public OpenALSound newSound (FileHandle file) {\r
String extension = file.extension();\r
- if (extension.equals("ogg")) return new OggSound(this, file);\r
+ if (extension.equals("ogg")) {\r
+ return new OggSound(this, file);\r
+ } else if (extension.equals("mp3")) {\r
+ return new Mp3Sound(this, file);\r
+ }\r
throw new GdxRuntimeException("Unknown file extension for sound: " + file);\r
}\r
\r
public OpenALMusic newMusic (FileHandle file) {\r
String extension = file.extension();\r
- if (extension.equals("ogg")) return new OggMusic(this, file);\r
+ if (extension.equals("ogg")) {\r
+ return new OggMusic(this, file);\r
+ } else if (extension.equals("mp3")) {\r
+ return new Mp3Music(this, file);\r
+ }\r
throw new GdxRuntimeException("Unknown file extension for music: " + file);\r
}\r
\r
--- /dev/null
+\r
+package com.baglogic.gdx.audio;\r
+\r
+import com.badlogic.gdx.ApplicationListener;\r
+import com.badlogic.gdx.Gdx;\r
+import com.badlogic.gdx.backends.lwjgl.LwjglApplication;\r
+\r
+public class Test implements ApplicationListener {\r
+ public void create () {\r
+ final OpenALAudio audio = new OpenALAudio(8);\r
+\r
+ Thread thread = new Thread() {\r
+ public void run () {\r
+ while (true) {\r
+ audio.update();\r
+ try {\r
+ Thread.sleep(100);\r
+ } catch (InterruptedException ignored) {\r
+ }\r
+ }\r
+ }\r
+ };\r
+ thread.setDaemon(true);\r
+ thread.start();\r
+\r
+ // String path = "C:/Dev/libgdx/tests/gdx-tests-lwjgl/data/cloudconnected.ogg";\r
+ String path = "C:/Users/Nate/Desktop/reggae/10 - Rainbow In The Sky.mp3";\r
+\r
+ OpenALSound sound = audio.newSound(Gdx.files.absolute(path));\r
+ sound.play();\r
+\r
+ // OpenALMusic music = audio.newMusic(Gdx.files.absolute(path));\r
+ // music.play();\r
+ }\r
+\r
+ public void resize (int width, int height) {\r
+ }\r
+\r
+ public void render () {\r
+ }\r
+\r
+ public void resume () {\r
+ }\r
+\r
+ public void pause () {\r
+ }\r
+\r
+ public void dispose () {\r
+ }\r
+\r
+ public static void main (String[] args) throws Exception {\r
+ new LwjglApplication(new Test(), "Test", 480, 320, false);\r
+ }\r
+}\r