Path: blob/master/SLICK_HOME/src/org/newdawn/slick/openal/AiffData.java
1461 views
/*1* Copyright (c) 2002-2004 LWJGL Project2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions are6* met:7*8* * Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10*11* * Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* * Neither the name of 'LWJGL' nor the names of16* its contributors may be used to endorse or promote products derived17* from this software without specific prior written permission.18*19* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS20* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED21* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR22* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR23* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,24* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,25* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR26* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF27* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING28* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS29* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.30*/31package org.newdawn.slick.openal;3233import java.io.BufferedInputStream;34import java.io.ByteArrayInputStream;35import java.io.IOException;36import java.io.InputStream;37import java.net.URL;38import java.nio.ByteBuffer;39import java.nio.ByteOrder;40import java.nio.ShortBuffer;4142import javax.sound.sampled.AudioFormat;43import javax.sound.sampled.AudioInputStream;44import javax.sound.sampled.AudioSystem;45import javax.sound.sampled.AudioFormat.Encoding;4647import org.lwjgl.openal.AL10;4849/**50*51* Utitlity class for loading wavefiles.52*53* @author Brian Matzon <[email protected]>54* @version $Revision: 2286 $55*/56public class AiffData {57/** actual AIFF data */58public final ByteBuffer data;5960/** format type of data */61public final int format;6263/** sample rate of data */64public final int samplerate;6566/**67* Creates a new AiffData68*69* @param data actual Aiffdata70* @param format format of Aiff data71* @param samplerate sample rate of data72*/73private AiffData(ByteBuffer data, int format, int samplerate) {74this.data = data;75this.format = format;76this.samplerate = samplerate;77}7879/**80* Disposes the Aiffdata81*/82public void dispose() {83data.clear();84}8586/**87* Creates a AiffData container from the specified url88*89* @param path URL to file90* @return AiffData containing data, or null if a failure occured91*/92public static AiffData create(URL path) {93try {94return create(95AudioSystem.getAudioInputStream(96new BufferedInputStream(path.openStream())));97} catch (Exception e) {98org.lwjgl.LWJGLUtil.log("Unable to create from: " + path);99e.printStackTrace();100return null;101}102}103104/**105* Creates a AiffData container from the specified in the classpath106*107* @param path path to file (relative, and in classpath)108* @return AiffData containing data, or null if a failure occured109*/110public static AiffData create(String path) {111return create(AiffData.class.getClassLoader().getResource(path));112}113114/**115* Creates a AiffData container from the specified inputstream116*117* @param is InputStream to read from118* @return AiffData containing data, or null if a failure occured119*/120public static AiffData create(InputStream is) {121try {122return create(123AudioSystem.getAudioInputStream(is));124} catch (Exception e) {125org.lwjgl.LWJGLUtil.log("Unable to create from inputstream");126e.printStackTrace();127return null;128}129}130131/**132* Creates a AiffData container from the specified bytes133*134* @param buffer array of bytes containing the complete Aiff file135* @return AiffData containing data, or null if a failure occured136*/137public static AiffData create(byte[] buffer) {138try {139return create(140AudioSystem.getAudioInputStream(141new BufferedInputStream(new ByteArrayInputStream(buffer))));142} catch (Exception e) {143e.printStackTrace();144return null;145}146}147148/**149* Creates a AiffData container from the specified ByetBuffer.150* If the buffer is backed by an array, it will be used directly,151* else the contents of the buffer will be copied using get(byte[]).152*153* @param buffer ByteBuffer containing sound file154* @return AiffData containing data, or null if a failure occured155*/156public static AiffData create(ByteBuffer buffer) {157try {158byte[] bytes = null;159160if(buffer.hasArray()) {161bytes = buffer.array();162} else {163bytes = new byte[buffer.capacity()];164buffer.get(bytes);165}166return create(bytes);167} catch (Exception e) {168e.printStackTrace();169return null;170}171}172173/**174* Creates a AiffData container from the specified stream175*176* @param ais AudioInputStream to read from177* @return AiffData containing data, or null if a failure occured178*/179public static AiffData create(AudioInputStream ais) {180//get format of data181AudioFormat audioformat = ais.getFormat();182183// get channels184int channels = 0;185if (audioformat.getChannels() == 1) {186if (audioformat.getSampleSizeInBits() == 8) {187channels = AL10.AL_FORMAT_MONO8;188} else if (audioformat.getSampleSizeInBits() == 16) {189channels = AL10.AL_FORMAT_MONO16;190} else {191throw new RuntimeException("Illegal sample size");192}193} else if (audioformat.getChannels() == 2) {194if (audioformat.getSampleSizeInBits() == 8) {195channels = AL10.AL_FORMAT_STEREO8;196} else if (audioformat.getSampleSizeInBits() == 16) {197channels = AL10.AL_FORMAT_STEREO16;198} else {199throw new RuntimeException("Illegal sample size");200}201} else {202throw new RuntimeException("Only mono or stereo is supported");203}204205//read data into buffer206byte[] buf =207new byte[audioformat.getChannels()208* (int) ais.getFrameLength()209* audioformat.getSampleSizeInBits()210/ 8];211int read = 0, total = 0;212try {213while ((read = ais.read(buf, total, buf.length - total)) != -1214&& total < buf.length) {215total += read;216}217} catch (IOException ioe) {218return null;219}220221//insert data into bytebuffer222ByteBuffer buffer = convertAudioBytes(audioformat, buf, audioformat.getSampleSizeInBits() == 16);223224//create our result225AiffData Aiffdata =226new AiffData(buffer, channels, (int) audioformat.getSampleRate());227228//close stream229try {230ais.close();231} catch (IOException ioe) {232}233234return Aiffdata;235}236237/**238* Convert the audio bytes into the stream239*240* @param format The audio format being decoded241* @param audio_bytes The audio byts242* @param two_bytes_data True if we using double byte data243* @return The byte bufer of data244*/245private static ByteBuffer convertAudioBytes(AudioFormat format, byte[] audio_bytes, boolean two_bytes_data) {246ByteBuffer dest = ByteBuffer.allocateDirect(audio_bytes.length);247dest.order(ByteOrder.nativeOrder());248ByteBuffer src = ByteBuffer.wrap(audio_bytes);249src.order(ByteOrder.BIG_ENDIAN);250if (two_bytes_data) {251ShortBuffer dest_short = dest.asShortBuffer();252ShortBuffer src_short = src.asShortBuffer();253while (src_short.hasRemaining())254dest_short.put(src_short.get());255} else {256while (src.hasRemaining()) {257byte b = src.get();258if (format.getEncoding() == Encoding.PCM_SIGNED) {259b = (byte) (b + 127);260}261dest.put(b);262}263}264dest.rewind();265return dest;266}267}268269270