Fixed mp3 playing, refactored to avoid duplicating code.
git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@153 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
+67
-23
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id$
|
// $Id: OggFileStream.java 119 2007-01-24 00:22:12Z dhoover $
|
||||||
//
|
//
|
||||||
// Narya library - tools for developing networked games
|
// Narya library - tools for developing networked games
|
||||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
package com.threerings.openal;
|
package com.threerings.openal;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -32,25 +34,31 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
import org.lwjgl.openal.AL10;
|
import org.lwjgl.openal.AL10;
|
||||||
|
|
||||||
import com.jmex.sound.openAL.objects.util.OggInputStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An audio stream read from one or more Ogg Vorbis files.
|
* An audio stream read from one or more files.
|
||||||
*/
|
*/
|
||||||
public class OggFileStream extends Stream
|
public class FileStream extends Stream
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Creates a new Ogg stream for the specified file.
|
* Registers a class of {@link StreamDecoder} for the specified file extension.
|
||||||
|
*/
|
||||||
|
public static void registerExtension (String extension, Class clazz)
|
||||||
|
{
|
||||||
|
_extensions.put(extension, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new stream for the specified file.
|
||||||
*
|
*
|
||||||
* @param loop whether or not to play the file in a continuous loop
|
* @param loop whether or not to play the file in a continuous loop
|
||||||
* if there's nothing on the queue
|
* if there's nothing on the queue
|
||||||
*/
|
*/
|
||||||
public OggFileStream (SoundManager soundmgr, File file, boolean loop)
|
public FileStream (SoundManager soundmgr, File file, boolean loop)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
super(soundmgr);
|
super(soundmgr);
|
||||||
_file = new OggFile(file, loop);
|
_file = new QueuedFile(file, loop);
|
||||||
_istream = new OggInputStream(new FileInputStream(file));
|
_decoder = createDecoder(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,49 +69,78 @@ public class OggFileStream extends Stream
|
|||||||
*/
|
*/
|
||||||
public void queueFile (File file, boolean loop)
|
public void queueFile (File file, boolean loop)
|
||||||
{
|
{
|
||||||
_queue.add(new OggFile(file, loop));
|
_queue.add(new QueuedFile(file, loop));
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
protected int getFormat ()
|
protected int getFormat ()
|
||||||
{
|
{
|
||||||
return (_istream.getFormat() == OggInputStream.FORMAT_MONO16) ?
|
return _decoder.getFormat();
|
||||||
AL10.AL_FORMAT_MONO16 : AL10.AL_FORMAT_STEREO16;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
protected int getFrequency ()
|
protected int getFrequency ()
|
||||||
{
|
{
|
||||||
return _istream.getRate();
|
return _decoder.getFrequency();
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
protected int populateBuffer (ByteBuffer buf)
|
protected int populateBuffer (ByteBuffer buf)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
int read = _istream.read(buf, buf.position(), buf.remaining());
|
int read = _decoder.read(buf);
|
||||||
while (buf.hasRemaining() && (!_queue.isEmpty() || _file.loop)) {
|
while (buf.hasRemaining() && (!_queue.isEmpty() || _file.loop)) {
|
||||||
if (!_queue.isEmpty()) {
|
if (!_queue.isEmpty()) {
|
||||||
_file = _queue.remove(0);
|
_file = _queue.remove(0);
|
||||||
}
|
}
|
||||||
_istream = new OggInputStream(new FileInputStream(_file.file));
|
_decoder = createDecoder(_file.file);
|
||||||
read = Math.max(0, read);
|
read = Math.max(0, read);
|
||||||
read += _istream.read(buf, buf.position(), buf.remaining());
|
read += _decoder.read(buf);
|
||||||
}
|
}
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The file currently being played. */
|
/**
|
||||||
protected OggFile _file;
|
* Creates and initializes a stream decoder for the specified file.
|
||||||
|
*/
|
||||||
|
protected StreamDecoder createDecoder (File file)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
String path = file.getPath();
|
||||||
|
int idx = path.lastIndexOf('.');
|
||||||
|
if (idx == -1) {
|
||||||
|
Log.warning("Missing extension for file [file=" + path + "].");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String extension = path.substring(idx+1);
|
||||||
|
Class clazz = _extensions.get(extension);
|
||||||
|
if (clazz == null) {
|
||||||
|
Log.warning("No decoder registered for extension [extension=" + extension +
|
||||||
|
", file=" + path + "].");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
StreamDecoder decoder;
|
||||||
|
try {
|
||||||
|
decoder = (StreamDecoder)clazz.newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Error instantiating decoder [file=" + path + ", error=" + e + "].");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
decoder.init(new FileInputStream(file));
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
|
||||||
/** The underlying Ogg input stream for the current file. */
|
/** The file currently being played. */
|
||||||
protected OggInputStream _istream;
|
protected QueuedFile _file;
|
||||||
|
|
||||||
|
/** The stream decoder for the current file. */
|
||||||
|
protected StreamDecoder _decoder;
|
||||||
|
|
||||||
/** The queue of files to play after the current one. */
|
/** The queue of files to play after the current one. */
|
||||||
protected ArrayList<OggFile> _queue = new ArrayList<OggFile>();
|
protected ArrayList<QueuedFile> _queue = new ArrayList<QueuedFile>();
|
||||||
|
|
||||||
/** A file queued for play. */
|
/** A file queued for play. */
|
||||||
protected class OggFile
|
protected class QueuedFile
|
||||||
{
|
{
|
||||||
/** The file to play. */
|
/** The file to play. */
|
||||||
public File file;
|
public File file;
|
||||||
@@ -112,10 +149,17 @@ public class OggFileStream extends Stream
|
|||||||
* in the queue. */
|
* in the queue. */
|
||||||
public boolean loop;
|
public boolean loop;
|
||||||
|
|
||||||
public OggFile (File file, boolean loop)
|
public QueuedFile (File file, boolean loop)
|
||||||
{
|
{
|
||||||
this.file = file;
|
this.file = file;
|
||||||
this.loop = loop;
|
this.loop = loop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Registered decoder classes. */
|
||||||
|
protected static HashMap<String, Class> _extensions = new HashMap<String, Class>();
|
||||||
|
static {
|
||||||
|
registerExtension("ogg", OggStreamDecoder.class);
|
||||||
|
registerExtension("mp3", Mp3StreamDecoder.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Nenya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
|
||||||
// http://www.threerings.net/code/nenya/
|
|
||||||
//
|
|
||||||
// This library 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 2.1 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library 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 along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
package com.threerings.openal;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ShortBuffer;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.lwjgl.openal.AL10;
|
|
||||||
|
|
||||||
import javazoom.jl.decoder.Bitstream;
|
|
||||||
import javazoom.jl.decoder.Decoder;
|
|
||||||
import javazoom.jl.decoder.Header;
|
|
||||||
import javazoom.jl.decoder.JavaLayerException;
|
|
||||||
import javazoom.jl.decoder.SampleBuffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An audio stream read from one or more mp3 files.
|
|
||||||
*/
|
|
||||||
public class Mp3FileStream extends Stream
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates a new stream for the specified file.
|
|
||||||
*
|
|
||||||
* @param loop whether or not to play the file in a continuous loop if there's nothing on the
|
|
||||||
* queue
|
|
||||||
*/
|
|
||||||
public Mp3FileStream (SoundManager soundmgr, File file, boolean loop)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
super(soundmgr);
|
|
||||||
_file = new Mp3File(file, loop);
|
|
||||||
_istream = new Bitstream(new FileInputStream(file));
|
|
||||||
_decoder = new Decoder();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a file to the queue of files to play.
|
|
||||||
*
|
|
||||||
* @param loop if true, play this file in a loop if there's nothing else on the queue
|
|
||||||
*/
|
|
||||||
public void queueFile (File file, boolean loop)
|
|
||||||
{
|
|
||||||
_queue.add(new Mp3File(file, loop));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override // from Stream
|
|
||||||
public void dispose ()
|
|
||||||
{
|
|
||||||
super.dispose();
|
|
||||||
|
|
||||||
// TODO: close our bitstream...
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
protected int getFormat ()
|
|
||||||
{
|
|
||||||
return AL10.AL_FORMAT_STEREO16;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
protected int getFrequency ()
|
|
||||||
{
|
|
||||||
return _frequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
protected int populateBuffer (ByteBuffer buf)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
if (_buffer == null) {
|
|
||||||
try {
|
|
||||||
Header h = _istream.readFrame();
|
|
||||||
for (int ii = 0; ii < 10 && (h == null); ii++) {
|
|
||||||
_istream.close();
|
|
||||||
Mp3File file = getNextFile();
|
|
||||||
if (file == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_istream = new Bitstream(new FileInputStream(file.file));
|
|
||||||
h = _istream.readFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
_buffer = (SampleBuffer)_decoder.decodeFrame(h, _istream);
|
|
||||||
_frequency = _buffer.getSampleFrequency();
|
|
||||||
|
|
||||||
} catch (JavaLayerException jle) {
|
|
||||||
throw (IOException)new IOException("JavaLayer decoding error").initCause(jle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int srem = buf.remaining();
|
|
||||||
ShortBuffer sbuf = buf.asShortBuffer();
|
|
||||||
int wrote = Math.min(_buffer.getBufferLength()-_offset, sbuf.remaining());
|
|
||||||
sbuf.put(_buffer.getBuffer(), _offset, wrote);
|
|
||||||
if (_offset + wrote >= _buffer.getBufferLength()) {
|
|
||||||
_buffer = null;
|
|
||||||
_offset = 0;
|
|
||||||
_istream.closeFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 2 * wrote;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Mp3File getNextFile ()
|
|
||||||
{
|
|
||||||
if (_file.loop) {
|
|
||||||
return _file;
|
|
||||||
} else if (!_queue.isEmpty()) {
|
|
||||||
return _queue.remove(0);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The file currently being played. */
|
|
||||||
protected Mp3File _file;
|
|
||||||
|
|
||||||
/** Handles reading the mp3 data. */
|
|
||||||
protected Bitstream _istream;
|
|
||||||
|
|
||||||
/** Handles decoding the mp3 data. */
|
|
||||||
protected Decoder _decoder;
|
|
||||||
|
|
||||||
/** The currently decoded frame, if any. */
|
|
||||||
protected SampleBuffer _buffer;
|
|
||||||
|
|
||||||
/** Our offset into the currently decoded frame. */
|
|
||||||
protected int _offset;
|
|
||||||
|
|
||||||
/** The frequency of the most recently processed frame. */
|
|
||||||
protected int _frequency;
|
|
||||||
|
|
||||||
/** The queue of files to play after the current one. */
|
|
||||||
protected ArrayList<Mp3File> _queue = new ArrayList<Mp3File>();
|
|
||||||
|
|
||||||
/** A file queued for play. */
|
|
||||||
protected class Mp3File
|
|
||||||
{
|
|
||||||
/** The file to play. */
|
|
||||||
public File file;
|
|
||||||
|
|
||||||
/** Whether or not to play the file in a loop when there's nothing in the queue. */
|
|
||||||
public boolean loop;
|
|
||||||
|
|
||||||
public Mp3File (File file, boolean loop) {
|
|
||||||
this.file = file;
|
|
||||||
this.loop = loop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Nenya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/nenya/
|
||||||
|
//
|
||||||
|
// This library 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 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library 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 along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.openal;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import org.lwjgl.openal.AL10;
|
||||||
|
|
||||||
|
import javazoom.jl.decoder.Bitstream;
|
||||||
|
import javazoom.jl.decoder.Decoder;
|
||||||
|
import javazoom.jl.decoder.Header;
|
||||||
|
import javazoom.jl.decoder.JavaLayerException;
|
||||||
|
import javazoom.jl.decoder.SampleBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes MP3 streams.
|
||||||
|
*/
|
||||||
|
public class Mp3StreamDecoder
|
||||||
|
implements StreamDecoder
|
||||||
|
{
|
||||||
|
// documentation inherited
|
||||||
|
public void init (InputStream in)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
_istream = new Bitstream(in);
|
||||||
|
try {
|
||||||
|
_header = _istream.readFrame();
|
||||||
|
} catch (JavaLayerException e) {
|
||||||
|
throw new IOException(e.toString());
|
||||||
|
}
|
||||||
|
_decoder = new Decoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public int getFormat ()
|
||||||
|
{
|
||||||
|
return AL10.AL_FORMAT_STEREO16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public int getFrequency ()
|
||||||
|
{
|
||||||
|
return _header.frequency();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public int read (ByteBuffer buf)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
ShortBuffer sbuf = buf.asShortBuffer();
|
||||||
|
int total = 0;
|
||||||
|
while (sbuf.hasRemaining() && _header != null) {
|
||||||
|
if (_buffer == null) {
|
||||||
|
try {
|
||||||
|
_buffer = (SampleBuffer)_decoder.decodeFrame(_header, _istream);
|
||||||
|
_istream.closeFrame();
|
||||||
|
_header = _istream.readFrame();
|
||||||
|
} catch (JavaLayerException e) {
|
||||||
|
throw new IOException(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int blen = _buffer.getBufferLength(),
|
||||||
|
length = Math.min(sbuf.remaining(), blen - _offset);
|
||||||
|
sbuf.put(_buffer.getBuffer(), _offset, length);
|
||||||
|
if ((_offset += length) >= blen) {
|
||||||
|
_offset = 0;
|
||||||
|
_buffer = null;
|
||||||
|
}
|
||||||
|
total += (length * 2);
|
||||||
|
}
|
||||||
|
buf.position(buf.position() + total);
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Handles reading the mp3 data. */
|
||||||
|
protected Bitstream _istream;
|
||||||
|
|
||||||
|
/** The mp3 header. */
|
||||||
|
protected Header _header;
|
||||||
|
|
||||||
|
/** Handles decoding the mp3 data. */
|
||||||
|
protected Decoder _decoder;
|
||||||
|
|
||||||
|
/** The sample buffer used for output. */
|
||||||
|
protected SampleBuffer _buffer;
|
||||||
|
|
||||||
|
/** Our offset into the currently decoded frame. */
|
||||||
|
protected int _offset;
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// $Id: OggFileStream.java 119 2007-01-24 00:22:12Z dhoover $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library 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 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library 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 along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.openal;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.lwjgl.openal.AL10;
|
||||||
|
|
||||||
|
import com.jmex.sound.openAL.objects.util.OggInputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes Ogg Vorbis streams.
|
||||||
|
*/
|
||||||
|
public class OggStreamDecoder
|
||||||
|
implements StreamDecoder
|
||||||
|
{
|
||||||
|
// documentation inherited
|
||||||
|
public void init (InputStream in)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
_istream = new OggInputStream(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public int getFormat ()
|
||||||
|
{
|
||||||
|
return (_istream.getFormat() == OggInputStream.FORMAT_MONO16) ?
|
||||||
|
AL10.AL_FORMAT_MONO16 : AL10.AL_FORMAT_STEREO16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public int getFrequency ()
|
||||||
|
{
|
||||||
|
return _istream.getRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public int read (ByteBuffer buf)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
return _istream.read(buf, buf.position(), buf.remaining());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The underlying Ogg input stream. */
|
||||||
|
protected OggInputStream _istream;
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ package com.threerings.openal;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
import org.lwjgl.BufferUtils;
|
import org.lwjgl.BufferUtils;
|
||||||
@@ -263,7 +264,7 @@ public abstract class Stream
|
|||||||
protected boolean populateBuffer (int bufferId)
|
protected boolean populateBuffer (int bufferId)
|
||||||
{
|
{
|
||||||
if (_abuf == null) {
|
if (_abuf == null) {
|
||||||
_abuf = ByteBuffer.allocateDirect(BUFFER_SIZE);
|
_abuf = ByteBuffer.allocateDirect(BUFFER_SIZE).order(ByteOrder.nativeOrder());
|
||||||
}
|
}
|
||||||
_abuf.clear();
|
_abuf.clear();
|
||||||
int read = 0;
|
int read = 0;
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// $Id: OggFileStream.java 119 2007-01-24 00:22:12Z dhoover $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library 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 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library 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 along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.openal;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes audio streams from data read from an {@link InputStream}.
|
||||||
|
*/
|
||||||
|
public interface StreamDecoder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initializes the decoder with its input stream.
|
||||||
|
*/
|
||||||
|
public abstract void init (InputStream in)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the sound format (see {@link Stream#getFormat}).
|
||||||
|
*/
|
||||||
|
public abstract int getFormat ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the sound frequency (see {@link Stream#getFrequency}).
|
||||||
|
*/
|
||||||
|
public abstract int getFrequency ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads as much data as will fit into the specified buffer.
|
||||||
|
*
|
||||||
|
* @return the number of bytes read. If less than or equal to zero, the decoder has reached
|
||||||
|
* the end of the stream.
|
||||||
|
*/
|
||||||
|
public abstract int read (ByteBuffer buf)
|
||||||
|
throws IOException;
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
package com.threerings.openal;
|
package com.threerings.openal;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import com.samskivert.util.Interval;
|
import com.samskivert.util.Interval;
|
||||||
@@ -17,7 +18,7 @@ public class TestSoundManager
|
|||||||
public static void main (String[] args)
|
public static void main (String[] args)
|
||||||
{
|
{
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
System.err.println("Usage: TestSoundManager sound.wav");
|
System.err.println("Usage: TestSoundManager sound.[wav|mp3|ogg]");
|
||||||
System.exit(-1);
|
System.exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,19 +32,35 @@ public class TestSoundManager
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
SoundManager smgr = SoundManager.createSoundManager(rqueue);
|
final SoundManager smgr = SoundManager.createSoundManager(rqueue);
|
||||||
ClipProvider provider = new WaveDataClipProvider();
|
ClipProvider provider = new WaveDataClipProvider();
|
||||||
final SoundGroup group = smgr.createGroup(provider, 5);
|
final SoundGroup group = smgr.createGroup(provider, 5);
|
||||||
final String path = args[0];
|
final String path = args[0];
|
||||||
|
|
||||||
// queue up an interval to play a sound over and over
|
String lpath = path.toLowerCase();
|
||||||
Interval i = new Interval(rqueue) {
|
if (lpath.endsWith("mp3") || lpath.endsWith(".ogg")) {
|
||||||
public void expired () {
|
// play the mp3/ogg file in a loop
|
||||||
Sound sound = group.getSound(path);
|
try {
|
||||||
sound.play(true);
|
new FileStream(smgr, new File(args[0]), true).play();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
};
|
Interval i = new Interval(rqueue) {
|
||||||
i.schedule(100L, true);
|
public void expired () {
|
||||||
|
smgr.updateStreams(0.1f);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
i.schedule(100L, true);
|
||||||
|
} else {
|
||||||
|
// queue up an interval to play a sound over and over
|
||||||
|
Interval i = new Interval(rqueue) {
|
||||||
|
public void expired () {
|
||||||
|
Sound sound = group.getSound(path);
|
||||||
|
sound.play(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
i.schedule(100L, true);
|
||||||
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
Runnable r = (Runnable)_queue.get();
|
Runnable r = (Runnable)_queue.get();
|
||||||
|
|||||||
Reference in New Issue
Block a user