From b16ae5f1abdf265d3dd48e523e8ed0aa3dd08d8f Mon Sep 17 00:00:00 2001 From: "Florian Richer (MrDev023)" Date: Wed, 23 Dec 2015 20:47:07 +0100 Subject: [PATCH] =?UTF-8?q?Correction=20du=20bug=20de=20lecture=20d'un=20f?= =?UTF-8?q?ichier=20Stereo=20au=20format=20OGG=20et=20ajout=20de=20la=20co?= =?UTF-8?q?mpatibilit=C3=A9=20avec=20le=20format=20WAV?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mrdev023/audio/Audio.java | 24 ++- src/mrdev023/audio/WaveData.java | 258 ++++++++++++++++++++++++ src/mrdev023/gameengine/GameEngine.java | 2 - 3 files changed, 278 insertions(+), 6 deletions(-) create mode 100644 src/mrdev023/audio/WaveData.java diff --git a/src/mrdev023/audio/Audio.java b/src/mrdev023/audio/Audio.java index 1a8b0d0..137da0b 100644 --- a/src/mrdev023/audio/Audio.java +++ b/src/mrdev023/audio/Audio.java @@ -34,6 +34,7 @@ public class Audio { //------------------------------------------------------ private int buffer,source; private String fileName; + private String format; //------------------------------------------------------ //Fonction global @@ -76,11 +77,28 @@ public class Audio { private void setSound() throws Exception{ if(fileName.endsWith(".ogg")){ loadOGGFormat(); + format = "OGG"; + }else if(fileName.endsWith(".wav")){ + loadWavFormat(); + format = "WAV"; }else{ throw new Exception("Format not supported !"); } alSourcei(source, AL_BUFFER, buffer); checkALError(); + int size = alGetBufferi(buffer,AL_SIZE); + int bits = alGetBufferi(buffer, AL_BITS); + int channels = alGetBufferi(buffer, AL_CHANNELS); + int freq = alGetBufferi(buffer, AL_FREQUENCY); + System.out.println(fileName + " loaded !" + " | TIME : " + (size/channels/(bits/8)/freq) + "s | BITS : " + bits + " | CHANNELS : " + channels + " | FREQUENCE : " + freq + " FORMAT : " + format); + } + + public void loadWavFormat() throws FileNotFoundException{ + WaveData soundData = WaveData.create(new BufferedInputStream(new FileInputStream(fileName))); + buffer = alGenBuffers(); + source = alGenSources(); + alBufferData(buffer, soundData.format, soundData.data, soundData.samplerate); + soundData.dispose(); } public void loadOGGFormat(){ @@ -93,9 +111,8 @@ public class Audio { if ( file.isFile() ) { FileInputStream fis = new FileInputStream(file); FileChannel fc = fis.getChannel(); - buff = BufferUtils.createByteBuffer((int)fc.size() + 1); - + while ( fc.read(buff) != -1 ) ; fis.close(); @@ -123,7 +140,7 @@ public class Audio { stb_vorbis_seek_start(decoder); int lengthSamples = stb_vorbis_stream_length_in_samples(decoder); - ByteBuffer pcm = BufferUtils.createByteBuffer(lengthSamples * channels); + ByteBuffer pcm = BufferUtils.createByteBuffer(lengthSamples * 2 * channels); stb_vorbis_get_samples_short_interleaved(decoder, channels, pcm, lengthSamples); float duration = stb_vorbis_stream_length_in_seconds(decoder); @@ -155,7 +172,6 @@ public class Audio { int bits = alGetBufferi(buffer, AL_BITS); int channels = alGetBufferi(buffer, AL_CHANNELS); int freq = alGetBufferi(buffer, AL_FREQUENCY); - System.out.println("SIZE : " + size + " | BITS : " + bits + " | CHANNELS : " + channels + " | FREQUENCE : " + freq); return size/channels/(bits/8)/freq; } diff --git a/src/mrdev023/audio/WaveData.java b/src/mrdev023/audio/WaveData.java new file mode 100644 index 0000000..e9fad89 --- /dev/null +++ b/src/mrdev023/audio/WaveData.java @@ -0,0 +1,258 @@ +package mrdev023.audio; + +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.ShortBuffer; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +import org.lwjgl.openal.AL10; + +import com.sun.media.sound.WaveFileReader; + +/** + * + * Utitlity class for loading wavefiles. + * + * @author Brian Matzon + * @version $Revision$ + * $Id$ + */ +public class WaveData { + /** actual wave data */ + public final ByteBuffer data; + + /** format type of data */ + public final int format; + + /** sample rate of data */ + public final int samplerate; + + /** + * Creates a new WaveData + * + * @param data actual wavedata + * @param format format of wave data + * @param samplerate sample rate of data + */ + private WaveData(ByteBuffer data, int format, int samplerate) { + this.data = data; + this.format = format; + this.samplerate = samplerate; + } + + /** + * Disposes the wavedata + */ + public void dispose() { + data.clear(); + } + + /** + * Creates a WaveData container from the specified url + * + * @param path URL to file + * @return WaveData containing data, or null if a failure occured + */ + public static WaveData create(URL path) { + try { + // due to an issue with AudioSystem.getAudioInputStream + // and mixing unsigned and signed code + // we will use the reader directly + WaveFileReader wfr = new WaveFileReader(); + return create(wfr.getAudioInputStream(new BufferedInputStream(path.openStream()))); + } catch (Exception e) { + System.err.println("Unable to create from: " + path + ", " + e.getMessage()); + return null; + } + } + + /** + * Creates a WaveData container from the specified in the classpath + * + * @param path path to file (relative, and in classpath) + * @return WaveData containing data, or null if a failure occured + */ + public static WaveData create(String path) { + return create(Thread.currentThread().getContextClassLoader().getResource(path)); + } + + /** + * Creates a WaveData container from the specified inputstream + * + * @param is InputStream to read from + * @return WaveData containing data, or null if a failure occured + */ + public static WaveData create(InputStream is) { + try { + return create( + AudioSystem.getAudioInputStream(is)); + } catch (Exception e) { + System.err.println("Unable to create from inputstream, " + e.getMessage()); + return null; + } + } + + /** + * Creates a WaveData container from the specified bytes + * + * @param buffer array of bytes containing the complete wave file + * @return WaveData containing data, or null if a failure occured + */ + public static WaveData create(byte[] buffer) { + try { + return create( + AudioSystem.getAudioInputStream( + new BufferedInputStream(new ByteArrayInputStream(buffer)))); + } catch (Exception e) { + System.err.println("Unable to create from byte array, " + e.getMessage()); + return null; + } + } + + /** + * Creates a WaveData container from the specified ByetBuffer. + * If the buffer is backed by an array, it will be used directly, + * else the contents of the buffer will be copied using get(byte[]). + * + * @param buffer ByteBuffer containing sound file + * @return WaveData containing data, or null if a failure occured + */ + public static WaveData create(ByteBuffer buffer) { + try { + byte[] bytes = null; + + if(buffer.hasArray()) { + bytes = buffer.array(); + } else { + bytes = new byte[buffer.capacity()]; + buffer.get(bytes); + } + return create(bytes); + } catch (Exception e) { + System.err.println("Unable to create from ByteBuffer, " + e.getMessage()); + return null; + } + } + + /** + * Creates a WaveData container from the specified stream + * + * @param ais AudioInputStream to read from + * @return WaveData containing data, or null if a failure occured + */ + public static WaveData create(AudioInputStream ais) { + //get format of data + AudioFormat audioformat = ais.getFormat(); + + // get channels + int channels = 0; + if (audioformat.getChannels() == 1) { + if (audioformat.getSampleSizeInBits() == 8) { + channels = AL10.AL_FORMAT_MONO8; + } else if (audioformat.getSampleSizeInBits() == 16) { + channels = AL10.AL_FORMAT_MONO16; + } else { + assert false : "Illegal sample size"; + } + } else if (audioformat.getChannels() == 2) { + if (audioformat.getSampleSizeInBits() == 8) { + channels = AL10.AL_FORMAT_STEREO8; + } else if (audioformat.getSampleSizeInBits() == 16) { + channels = AL10.AL_FORMAT_STEREO16; + } else { + assert false : "Illegal sample size"; + } + } else { + assert false : "Only mono or stereo is supported"; + } + + //read data into buffer + ByteBuffer buffer = null; + try { + int available = ais.available(); + if(available <= 0) { + available = ais.getFormat().getChannels() * (int) ais.getFrameLength() * ais.getFormat().getSampleSizeInBits() / 8; + } + byte[] buf = new byte[ais.available()]; + int read = 0, total = 0; + while ((read = ais.read(buf, total, buf.length - total)) != -1 + && total < buf.length) { + total += read; + } + buffer = convertAudioBytes(buf, audioformat.getSampleSizeInBits() == 16, audioformat.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); + } catch (IOException ioe) { + return null; + } + + + //create our result + WaveData wavedata = + new WaveData(buffer, channels, (int) audioformat.getSampleRate()); + + //close stream + try { + ais.close(); + } catch (IOException ioe) { + } + + return wavedata; + } + + private static ByteBuffer convertAudioBytes(byte[] audio_bytes, boolean two_bytes_data, ByteOrder order) { + ByteBuffer dest = ByteBuffer.allocateDirect(audio_bytes.length); + dest.order(ByteOrder.nativeOrder()); + ByteBuffer src = ByteBuffer.wrap(audio_bytes); + src.order(order); + if (two_bytes_data) { + ShortBuffer dest_short = dest.asShortBuffer(); + ShortBuffer src_short = src.asShortBuffer(); + while (src_short.hasRemaining()) + dest_short.put(src_short.get()); + } else { + while (src.hasRemaining()) + dest.put(src.get()); + } + dest.rewind(); + return dest; + } +} diff --git a/src/mrdev023/gameengine/GameEngine.java b/src/mrdev023/gameengine/GameEngine.java index 1fb610c..752c085 100644 --- a/src/mrdev023/gameengine/GameEngine.java +++ b/src/mrdev023/gameengine/GameEngine.java @@ -48,7 +48,6 @@ public class GameEngine { Display.setMouseGrabbed(true); try { a = new Audio("res/audio/test.ogg"); - System.err.println(a.getDurationInSeconds()); a.playSound(); } catch (Exception e) { // TODO Auto-generated catch block @@ -85,7 +84,6 @@ public class GameEngine { if(Timer.getMillisTime("info") >= 1000){ Display.setTitle(TITLE + " | Fps:" + FPS + " Ticks:" + TICKS + " | " + camera.getPos() + " " + camera.getRot()); - System.out.println(a.getPosition()); FPS = 0; TICKS = 0; Timer.setValue("info", Timer.getNanoTime("info") - 1000000000);