All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.lessvoid.nifty.sound.openal.slick.AiffData Maven / Gradle / Ivy

Go to download

This is an OpenAL/lwjgl based SoundDevice for Nifty GUI. It was extracted out of Slick2D to be independent of the whole Slick2D library and to be used with none Slick2D based renderes. All credits for the original code go to Kevin Glass and all Slick2D contributers.

There is a newer version: 1.4.3
Show newest version
/* 
 * Copyright (c) 2002-2004 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.
 */
package de.lessvoid.nifty.sound.openal.slick;

import org.lwjgl.openal.AL10;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
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;

/**
 * Utility class for loading wave files.
 *
 * @author Brian Matzon 
 * @version $Revision: 2286 $
 */
public class AiffData {
  /**
   * actual AIFF data
   */
  @Nonnull
  public final ByteBuffer data;

  /**
   * format type of data
   */
  public final int format;

  /**
   * sample rate of data
   */
  public final int samplerate;

  /**
   * Creates a new AiffData
   *
   * @param data       actual Aiffdata
   * @param format     format of Aiff data
   * @param samplerate sample rate of data
   */
  private AiffData(@Nonnull ByteBuffer data, int format, int samplerate) {
    this.data = data;
    this.format = format;
    this.samplerate = samplerate;
  }

  /**
   * Disposes the Aiffdata
   */
  public void dispose() {
    data.clear();
  }

  /**
   * Creates a AiffData container from the specified url
   *
   * @param path URL to file
   * @return AiffData containing data, or null if a failure occured
   */
  @Nullable
  public static AiffData create(@Nonnull URL path) {
    try {
      return create(
          AudioSystem.getAudioInputStream(
              new BufferedInputStream(path.openStream())));
    } catch (Exception e) {
      org.lwjgl.LWJGLUtil.log("Unable to create from: " + path);
      e.printStackTrace();
      return null;
    }
  }

  /**
   * Creates a AiffData container from the specified in the classpath
   *
   * @param path path to file (relative, and in classpath)
   * @return AiffData containing data, or null if a failure occured
   */
  @Nullable
  public static AiffData create(String path) {
    //noinspection ConstantConditions
    return create(AiffData.class.getClassLoader().getResource(path));
  }

  /**
   * Creates a AiffData container from the specified inputstream
   *
   * @param is InputStream to read from
   * @return AiffData containing data, or null if a failure occured
   */
  @Nullable
  public static AiffData create(InputStream is) {
    try {
      return create(
          AudioSystem.getAudioInputStream(is));
    } catch (Exception e) {
      org.lwjgl.LWJGLUtil.log("Unable to create from inputstream");
      e.printStackTrace();
      return null;
    }
  }

  /**
   * Creates a AiffData container from the specified bytes
   *
   * @param buffer array of bytes containing the complete Aiff file
   * @return AiffData containing data, or null if a failure occured
   */
  @Nullable
  public static AiffData create(byte[] buffer) {
    try {
      return create(
          AudioSystem.getAudioInputStream(
              new BufferedInputStream(new ByteArrayInputStream(buffer))));
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * Creates a AiffData 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 AiffData containing data, or null if a failure occured
   */
  @Nullable
  public static AiffData create(@Nonnull ByteBuffer buffer) {
    try {
      byte[] bytes;

      if (buffer.hasArray()) {
        bytes = buffer.array();
      } else {
        bytes = new byte[buffer.capacity()];
        buffer.get(bytes);
      }
      return create(bytes);
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * Creates a AiffData container from the specified stream
   *
   * @param ais AudioInputStream to read from
   * @return AiffData containing data, or null if a failure occured
   */
  @Nullable
  public static AiffData create(@Nonnull AudioInputStream ais) {
    //get format of data
    AudioFormat audioformat = ais.getFormat();

    // get channels
    int channels;
    if (audioformat.getChannels() == 1) {
      if (audioformat.getSampleSizeInBits() == 8) {
        channels = AL10.AL_FORMAT_MONO8;
      } else if (audioformat.getSampleSizeInBits() == 16) {
        channels = AL10.AL_FORMAT_MONO16;
      } else {
        throw new RuntimeException("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 {
        throw new RuntimeException("Illegal sample size");
      }
    } else {
      throw new RuntimeException("Only mono or stereo is supported");
    }

    //read data into buffer
    byte[] buf =
        new byte[audioformat.getChannels()
            * (int) ais.getFrameLength()
            * audioformat.getSampleSizeInBits()
            / 8];
    int read, total = 0;
    try {
      while ((read = ais.read(buf, total, buf.length - total)) != -1
          && total < buf.length) {
        total += read;
      }
    } catch (IOException ioe) {
      return null;
    }

    //insert data into bytebuffer
    ByteBuffer buffer = convertAudioBytes(audioformat, buf, audioformat.getSampleSizeInBits() == 16);

    //create our result
    AiffData Aiffdata =
        new AiffData(buffer, channels, (int) audioformat.getSampleRate());

    //close stream
    try {
      ais.close();
    } catch (IOException ignored) {
    }

    return Aiffdata;
  }

  /**
   * Convert the audio bytes into the stream
   *
   * @param format         The audio format being decoded
   * @param audio_bytes    The audio byts
   * @param two_bytes_data True if we using double byte data
   * @return The byte bufer of data
   */
  private static ByteBuffer convertAudioBytes(
      @Nonnull AudioFormat format,
      @Nonnull byte[] audio_bytes,
      boolean two_bytes_data) {
    ByteBuffer dest = ByteBuffer.allocateDirect(audio_bytes.length);
    dest.order(ByteOrder.nativeOrder());
    ByteBuffer src = ByteBuffer.wrap(audio_bytes);
    src.order(ByteOrder.BIG_ENDIAN);
    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()) {
        byte b = src.get();
        if (format.getEncoding() == Encoding.PCM_SIGNED) {
          b = (byte) (b + 127);
        }
        dest.put(b);
      }
    }
    dest.rewind();
    return dest;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy