Package com.badlogic.gdx.backends.openal

Source Code of com.badlogic.gdx.backends.openal.OpenALAudio

/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/

package com.badlogic.gdx.backends.openal;

import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.AL10;

import com.badlogic.gdx.Audio;
import com.badlogic.gdx.audio.AudioDevice;
import com.badlogic.gdx.audio.AudioRecorder;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.IntArray;
import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.LongMap;
import com.badlogic.gdx.utils.ObjectMap;

import static org.lwjgl.openal.AL10.*;

/** @author Nathan Sweet */
public class OpenALAudio implements Audio {
  private final int deviceBufferSize;
  private final int deviceBufferCount;
  private IntArray idleSources, allSources;
  private LongMap<Integer> soundIdToSource;
  private IntMap<Long> sourceToSoundId;
  private long nextSoundId = 0;
  private ObjectMap<String, Class<? extends OpenALSound>> extensionToSoundClass = new ObjectMap();
  private ObjectMap<String, Class<? extends OpenALMusic>> extensionToMusicClass = new ObjectMap();

  Array<OpenALMusic> music = new Array(false, 1, OpenALMusic.class);
  boolean noDevice = false;

  public OpenALAudio () {
    this(16, 9, 512);
  }

  public OpenALAudio (int simultaneousSources, int deviceBufferCount, int deviceBufferSize) {
    this.deviceBufferSize = deviceBufferSize;
    this.deviceBufferCount = deviceBufferCount;

    registerSound("ogg", Ogg.Sound.class);
    registerMusic("ogg", Ogg.Music.class);
    registerSound("wav", Wav.Sound.class);
    registerMusic("wav", Wav.Music.class);
    registerSound("mp3", Mp3.Sound.class);
    registerMusic("mp3", Mp3.Music.class);

    try {
      AL.create();
    } catch (LWJGLException ex) {
      noDevice = true;
      ex.printStackTrace();
      return;
    }

    allSources = new IntArray(false, simultaneousSources);
    for (int i = 0; i < simultaneousSources; i++) {
      int sourceID = alGenSources();
      if (alGetError() != AL_NO_ERROR) break;
      allSources.add(sourceID);
    }
    idleSources = new IntArray(allSources);
    soundIdToSource = new LongMap<Integer>();
    sourceToSoundId = new IntMap<Long>();

    FloatBuffer orientation = (FloatBuffer)BufferUtils.createFloatBuffer(6)
      .put(new float[] {0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f}).flip();
    alListener(AL_ORIENTATION, orientation);
    FloatBuffer velocity = (FloatBuffer)BufferUtils.createFloatBuffer(3).put(new float[] {0.0f, 0.0f, 0.0f}).flip();
    alListener(AL_VELOCITY, velocity);
    FloatBuffer position = (FloatBuffer)BufferUtils.createFloatBuffer(3).put(new float[] {0.0f, 0.0f, 0.0f}).flip();
    alListener(AL_POSITION, position);
  }

  public void registerSound (String extension, Class<? extends OpenALSound> soundClass) {
    if (extension == null) throw new IllegalArgumentException("extension cannot be null.");
    if (soundClass == null) throw new IllegalArgumentException("soundClass cannot be null.");
    extensionToSoundClass.put(extension, soundClass);
  }

  public void registerMusic (String extension, Class<? extends OpenALMusic> musicClass) {
    if (extension == null) throw new IllegalArgumentException("extension cannot be null.");
    if (musicClass == null) throw new IllegalArgumentException("musicClass cannot be null.");
    extensionToMusicClass.put(extension, musicClass);
  }

  public OpenALSound newSound (FileHandle file) {
    if (file == null) throw new IllegalArgumentException("file cannot be null.");
    Class<? extends OpenALSound> soundClass = extensionToSoundClass.get(file.extension().toLowerCase());
    if (soundClass == null) throw new GdxRuntimeException("Unknown file extension for sound: " + file);
    try {
      return soundClass.getConstructor(new Class[] {OpenALAudio.class, FileHandle.class}).newInstance(this, file);
    } catch (Exception ex) {
      throw new GdxRuntimeException("Error creating sound " + soundClass.getName() + " for file: " + file, ex);
    }
  }

  public OpenALMusic newMusic (FileHandle file) {
    if (file == null) throw new IllegalArgumentException("file cannot be null.");
    Class<? extends OpenALMusic> musicClass = extensionToMusicClass.get(file.extension().toLowerCase());
    if (musicClass == null) throw new GdxRuntimeException("Unknown file extension for music: " + file);
    try {
      return musicClass.getConstructor(new Class[] {OpenALAudio.class, FileHandle.class}).newInstance(this, file);
    } catch (Exception ex) {
      throw new GdxRuntimeException("Error creating music " + musicClass.getName() + " for file: " + file, ex);
    }
  }

  int obtainSource (boolean isMusic) {
    if (noDevice) return 0;
    for (int i = 0, n = idleSources.size; i < n; i++) {
      int sourceId = idleSources.get(i);
      int state = alGetSourcei(sourceId, AL_SOURCE_STATE);
      if (state != AL_PLAYING && state != AL_PAUSED) {
        if (isMusic) {
          idleSources.removeIndex(i);
        } else {
          if (sourceToSoundId.containsKey(sourceId)) {
            long soundId = sourceToSoundId.get(sourceId);
            sourceToSoundId.remove(sourceId);
            soundIdToSource.remove(soundId);
          }

          long soundId = nextSoundId++;
          sourceToSoundId.put(sourceId, soundId);
          soundIdToSource.put(soundId, sourceId);
        }
        alSourceStop(sourceId);
        alSourcei(sourceId, AL_BUFFER, 0);
        AL10.alSourcef(sourceId, AL10.AL_GAIN, 1);
        AL10.alSourcef(sourceId, AL10.AL_PITCH, 1);
        AL10.alSource3f(sourceId, AL10.AL_POSITION, 0, 0, 1f);
        return sourceId;
      }
    }
    return -1;
  }

  void freeSource (int sourceID) {
    if (noDevice) return;
    alSourceStop(sourceID);
    alSourcei(sourceID, AL_BUFFER, 0);
    if (sourceToSoundId.containsKey(sourceID)) {
      long soundId = sourceToSoundId.remove(sourceID);
      soundIdToSource.remove(soundId);
    }
    idleSources.add(sourceID);
  }

  void freeBuffer (int bufferID) {
    if (noDevice) return;
    for (int i = 0, n = idleSources.size; i < n; i++) {
      int sourceID = idleSources.get(i);
      if (alGetSourcei(sourceID, AL_BUFFER) == bufferID) {
        if (sourceToSoundId.containsKey(sourceID)) {
          long soundId = sourceToSoundId.remove(sourceID);
          soundIdToSource.remove(soundId);
        }
        alSourceStop(sourceID);
        alSourcei(sourceID, AL_BUFFER, 0);
      }
    }
  }

  void stopSourcesWithBuffer (int bufferID) {
    if (noDevice) return;
    for (int i = 0, n = idleSources.size; i < n; i++) {
      int sourceID = idleSources.get(i);
      if (alGetSourcei(sourceID, AL_BUFFER) == bufferID) {
        if (sourceToSoundId.containsKey(sourceID)) {
          long soundId = sourceToSoundId.remove(sourceID);
          soundIdToSource.remove(soundId);
        }
        alSourceStop(sourceID);
      }
    }
  }
 
  void pauseSourcesWithBuffer (int bufferID) {
    if (noDevice) return;
    for (int i = 0, n = idleSources.size; i < n; i++) {
      int sourceID = idleSources.get(i);
      if (alGetSourcei(sourceID, AL_BUFFER) == bufferID)
        alSourcePause(sourceID);
    }
  }
 
  void resumeSourcesWithBuffer (int bufferID) {
    if (noDevice) return;
    for (int i = 0, n = idleSources.size; i < n; i++) {
      int sourceID = idleSources.get(i);
      if (alGetSourcei(sourceID, AL_BUFFER) == bufferID) {
        if (alGetSourcei(sourceID, AL_SOURCE_STATE) == AL_PAUSED)
          alSourcePlay(sourceID);
      }
    }
  }

  public void update () {
    if (noDevice) return;
    for (int i = 0; i < music.size; i++)
      music.items[i].update();
  }

  public long getSoundId (int sourceId) {
    if (!sourceToSoundId.containsKey(sourceId)) return -1;
    return sourceToSoundId.get(sourceId);
  }

  public void stopSound (long soundId) {
    if (!soundIdToSource.containsKey(soundId)) return;
    int sourceId = soundIdToSource.get(soundId);
    alSourceStop(sourceId);
  }
 
  public void pauseSound (long soundId) {
    if (!soundIdToSource.containsKey(soundId)) return;
    int sourceId = soundIdToSource.get(soundId);
    alSourcePause(sourceId);
  }
 
  public void resumeSound (long soundId) {
    if (!soundIdToSource.containsKey(soundId)) return;
    int sourceId = soundIdToSource.get(soundId);
    if (alGetSourcei(sourceId, AL_SOURCE_STATE) == AL_PAUSED)
      alSourcePlay(sourceId);
  }

  public void setSoundGain (long soundId, float volume) {
    if (!soundIdToSource.containsKey(soundId)) return;
    int sourceId = soundIdToSource.get(soundId);
    AL10.alSourcef(sourceId, AL10.AL_GAIN, volume);
  }

  public void setSoundLooping (long soundId, boolean looping) {
    if (!soundIdToSource.containsKey(soundId)) return;
    int sourceId = soundIdToSource.get(soundId);
    alSourcei(sourceId, AL10.AL_LOOPING, looping ? AL10.AL_TRUE : AL10.AL_FALSE);
  }

  public void setSoundPitch (long soundId, float pitch) {
    if (!soundIdToSource.containsKey(soundId)) return;
    int sourceId = soundIdToSource.get(soundId);
    AL10.alSourcef(sourceId, AL10.AL_PITCH, pitch);
  }

  public void setSoundPan (long soundId, float pan, float volume) {
    if (!soundIdToSource.containsKey(soundId)) return;
    int sourceId = soundIdToSource.get(soundId);

    AL10.alSource3f(sourceId, AL10.AL_POSITION, MathUtils.cos((pan - 1) * MathUtils.PI / 2), 0,
      MathUtils.sin((pan + 1) * MathUtils.PI / 2));
    AL10.alSourcef(sourceId, AL10.AL_GAIN, volume);
  }

  public void dispose () {
    if (noDevice) return;
    for (int i = 0, n = allSources.size; i < n; i++) {
      int sourceID = allSources.get(i);
      int state = alGetSourcei(sourceID, AL_SOURCE_STATE);
      if (state != AL_STOPPED) alSourceStop(sourceID);
      alDeleteSources(sourceID);
    }

    sourceToSoundId.clear();
    soundIdToSource.clear();

    AL.destroy();
    while (AL.isCreated()) {
      try {
        Thread.sleep(10);
      } catch (InterruptedException e) {
      }
    }
  }

  public AudioDevice newAudioDevice (int sampleRate, final boolean isMono) {
    if (noDevice) return new AudioDevice() {
      @Override
      public void writeSamples (float[] samples, int offset, int numSamples) {
      }

      @Override
      public void writeSamples (short[] samples, int offset, int numSamples) {
      }

      @Override
      public void setVolume (float volume) {
      }

      @Override
      public boolean isMono () {
        return isMono;
      }

      @Override
      public int getLatency () {
        return 0;
      }

      @Override
      public void dispose () {
      }
    };
    return new OpenALAudioDevice(this, sampleRate, isMono, deviceBufferSize, deviceBufferCount);
  }

  public AudioRecorder newAudioRecorder (int samplingRate, boolean isMono) {
    if (noDevice) return new AudioRecorder() {
      @Override
      public void read (short[] samples, int offset, int numSamples) {
      }

      @Override
      public void dispose () {
      }
    };
    return new JavaSoundAudioRecorder(samplingRate, isMono);
  }
}
TOP

Related Classes of com.badlogic.gdx.backends.openal.OpenALAudio

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.