/* This file is part of jpcsp. Jpcsp is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Jpcsp 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Jpcsp. If not, see <http://www.gnu.org/licenses/>. */ package jpcsp.test; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; import java.util.HashSet; import java.util.Set; import jpcsp.util.LWJGLFixer; import org.lwjgl.LWJGLException; import org.lwjgl.openal.AL; import org.lwjgl.openal.AL10; public class OpenAL { static { LWJGLFixer.fixOnce(); } private static Set<Integer> freeBuffers = new HashSet<Integer>(); private static boolean isRawFile = false; private static int sampleRate = 48000; // 44100 or 48000 private static int read8(FileInputStream fis) throws IOException { byte[] buffer = new byte[1]; fis.read(buffer); return ((int) buffer[0]) & 0xFF; } private static int read32(FileInputStream fis) throws IOException { int n1 = read8(fis); int n2 = read8(fis); int n3 = read8(fis); int n4 = read8(fis); return n1 | (n2 << 8) | (n3 << 16) | (n4 << 24); } private static void read(FileInputStream fis, int alSource) { try { byte[] buffer; int length; if (isRawFile) { int fileSize = read32(fis); read32(fis); // skip timestamp length = fileSize - 8; if (length > 0) { buffer = new byte[length]; length = fis.read(buffer); } else { buffer = null; } } else { buffer = new byte[10240]; length = fis.read(buffer); } if (length <= 0) { AL10.alSourceStop(alSource); fis.close(); return; } ByteBuffer directBuffer = ByteBuffer.allocateDirect(length); directBuffer.put(buffer, 0, length); directBuffer.rewind(); while (true) { int alBuffer = -1; if (freeBuffers.isEmpty()) { int availableBuffers = AL10.alGetSourcei(alSource, AL10.AL_BUFFERS_PROCESSED); if (availableBuffers > 0) { alBuffer = AL10.alSourceUnqueueBuffers(alSource); } } else { alBuffer = freeBuffers.iterator().next(); freeBuffers.remove(alBuffer); } if (alBuffer >= 0) { AL10.alBufferData(alBuffer, AL10.AL_FORMAT_STEREO16, directBuffer, sampleRate); AL10.alSourceQueueBuffers(alSource, alBuffer); break; } } } catch (IOException e) { e.printStackTrace(); } } private static String getStateName(int state) { switch (state) { case AL10.AL_PLAYING: return "Playing"; case AL10.AL_PAUSED: return "Paused"; case AL10.AL_STOPPED: return "Stopped"; } return String.format("%d", state); } private static void displayError(String text) { int errorCode = AL10.alGetError(); if (errorCode != 0) { System.out.println(String.format("Error %s %d", text, errorCode)); } } /** * @param args */ public static void main(String[] args) { try { AL.create(); //FileInputStream fis = new FileInputStream("tmp/xxDISCIDxx/Atrac/Atrac-NNNNNNNN-NNNNNNNN.at3.decoded"); FileInputStream fis = new FileInputStream("tmp/xxDISCIDxx/Mpeg-nnnn/AudioStream-0.raw"); isRawFile = true; if (isRawFile) { read32(fis); } for (int i = 0; i < 5; i++) { freeBuffers.add(AL10.alGenBuffers()); displayError("alGenBuffers"); } int alSource = AL10.alGenSources(); displayError("alGenSources"); // AL10.alSource3f(alSource, AL10.AL_POSITION, 0.0f, 0.0f, 0.0f); // displayError("AL_POSITION"); // AL10.alSource3f(alSource, AL10.AL_VELOCITY, 0.0f, 0.0f, 0.0f); // displayError("AL_VELOCITY"); // AL10.alSource3f(alSource, AL10.AL_DIRECTION, 0.0f, 0.0f, 0.0f); // displayError("AL_DIRECTION"); // AL10.alSourcei(alSource, AL10.AL_SOURCE_RELATIVE, AL10.AL_TRUE); // displayError("AL_SOURCE_RELATIVE"); // AL10.alSourcef(alSource, AL10.AL_PITCH, 1.0f); // displayError("AL_PITCH"); // AL10.alSourcef(alSource, AL10.AL_GAIN, 1.0f); // displayError("AL_GAIN"); AL10.alSourcei(alSource, AL10.AL_LOOPING, AL10.AL_FALSE); displayError("AL_LOOPING"); read(fis, alSource); AL10.alSourcePlay(alSource); displayError("alSourcePlay"); int previousState = -1; while (true) { int state = AL10.alGetSourcei(alSource, AL10.AL_SOURCE_STATE); if (state != previousState) { System.out.println(String.format("State %s", getStateName(state))); previousState = state; } if (state != AL10.AL_PLAYING && state != AL10.AL_INITIAL) { break; } read(fis, alSource); } AL10.alSourceStop(alSource); } catch (LWJGLException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }