/**
* Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* -Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* -Redistribution 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 Sun Microsystems, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS
* LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A
* RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
* IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT
* OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use in the
* design, construction, operation or maintenance of any nuclear facility.
*
*/
package demos.devmaster.lesson5;
import java.io.*;
import java.nio.*;
import java.util.*;
// For the gui
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
import net.java.games.joal.*;
import net.java.games.joal.util.*;
/**
* Adapted from DevMaster
* MultipleSources Tutorial
* by Jesse Maurais.
*
* @author Athomas Goldberg
* @author Kenneth Russell
*/
public class SourcesSharingBuffers {
static ALC alc;
static AL al;
// These index the buffers.
public static final int THUNDER = 0;
public static final int WATERDROP = 1;
public static final int STREAM = 2;
public static final int RAIN = 3;
public static final int CHIMES = 4;
public static final int OCEAN = 5;
public static final int NUM_BUFFERS = 6;
// Buffers hold sound data.
static int[] buffers = new int[NUM_BUFFERS];
// A list of sources for multiple emissions.
static List sources = new ArrayList();
// Position of the source sounds.
static float[] sourcePos = { 0.0f, 0.0f, 0.0f };
// Velocity of the source sounds.
static float[] sourceVel = { 0.0f, 0.0f, 0.0f };
// Position of the listener.
static float[] listenerPos = { 0.0f, 0.0f, 0.0f };
// Velocity of the listener.
static float[] listenerVel = { 0.0f, 0.0f, 0.0f };
// Orientation of the listener. (first 3 elements are "at", second 3 are "up")
static float[] listenerOri = { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f };
static void initOpenAL() throws ALException {
alc = ALFactory.getALC();
al = ALFactory.getAL();
ALCdevice device;
ALCcontext context;
String deviceSpecifier;
// Get handle to default device.
device = alc.alcOpenDevice(null);
if (device == null) {
throw new ALException("Error opening default OpenAL device");
}
// Get the device specifier.
deviceSpecifier = alc.alcGetString(device, ALC.ALC_DEVICE_SPECIFIER);
if (deviceSpecifier == null) {
throw new ALException("Error getting specifier for default OpenAL device");
}
System.out.println("Using device " + deviceSpecifier);
// Create audio context.
context = alc.alcCreateContext(device, null);
if (context == null) {
throw new ALException("Error creating OpenAL context");
}
// Set active context.
alc.alcMakeContextCurrent(context);
// Check for an error.
if (alc.alcGetError(device) != ALC.ALC_NO_ERROR) {
throw new ALException("Error making OpenAL context current");
}
}
static void exitOpenAL() {
ALCcontext curContext;
ALCdevice curDevice;
// Get the current context.
curContext = alc.alcGetCurrentContext();
// Get the device used by that context.
curDevice = alc.alcGetContextsDevice(curContext);
// Reset the current context to NULL.
alc.alcMakeContextCurrent(null);
// Release the context and the device.
alc.alcDestroyContext(curContext);
alc.alcCloseDevice(curDevice);
}
static int loadALData() {
// Variables to load into.
int[] format = new int[1];
int[] size = new int[1];
ByteBuffer[] data = new ByteBuffer[1];
int[] freq = new int[1];
int[] loop = new int[1];
// Load wav data into buffers.
al.alGenBuffers(NUM_BUFFERS, buffers, 0);
if(al.alGetError() != AL.AL_NO_ERROR)
return AL.AL_FALSE;
ALut.alutLoadWAVFile(SourcesSharingBuffers.class.getClassLoader().getResourceAsStream("demos/data/thunder.wav"),
format, data, size, freq, loop);
al.alBufferData(buffers[THUNDER], format[0], data[0], size[0], freq[0]);
ALut.alutLoadWAVFile(SourcesSharingBuffers.class.getClassLoader().getResourceAsStream("demos/data/waterdrop.wav"),
format, data, size, freq, loop);
al.alBufferData(buffers[WATERDROP], format[0], data[0], size[0], freq[0]);
ALut.alutLoadWAVFile(SourcesSharingBuffers.class.getClassLoader().getResourceAsStream("demos/data/stream.wav"),
format, data, size, freq, loop);
al.alBufferData(buffers[STREAM], format[0], data[0], size[0], freq[0]);
ALut.alutLoadWAVFile(SourcesSharingBuffers.class.getClassLoader().getResourceAsStream("demos/data/rain.wav"),
format, data, size, freq, loop);
al.alBufferData(buffers[RAIN], format[0], data[0], size[0], freq[0]);
ALut.alutLoadWAVFile(SourcesSharingBuffers.class.getClassLoader().getResourceAsStream("demos/data/ocean.wav"),
format, data, size, freq, loop);
al.alBufferData(buffers[OCEAN], format[0], data[0], size[0], freq[0]);
ALut.alutLoadWAVFile(SourcesSharingBuffers.class.getClassLoader().getResourceAsStream("demos/data/chimes.wav"),
format, data, size, freq, loop);
al.alBufferData(buffers[CHIMES], format[0], data[0], size[0], freq[0]);
// Do another error check and return.
if (al.alGetError() != AL.AL_NO_ERROR)
return AL.AL_FALSE;
return AL.AL_TRUE;
}
static void addSource(int type) {
int[] source = new int[1];
al.alGenSources(1, source, 0);
if (al.alGetError() != AL.AL_NO_ERROR) {
System.err.println("Error generating audio source.");
System.exit(1);
}
al.alSourcei (source[0], AL.AL_BUFFER, buffers[type]);
al.alSourcef (source[0], AL.AL_PITCH, 1.0f );
al.alSourcef (source[0], AL.AL_GAIN, 1.0f );
al.alSourcefv(source[0], AL.AL_POSITION, sourcePos , 0);
al.alSourcefv(source[0], AL.AL_VELOCITY, sourceVel , 0);
al.alSourcei (source[0], AL.AL_LOOPING, AL.AL_TRUE );
al.alSourcePlay(source[0]);
sources.add(new Integer(source[0]));
}
static void setListenerValues() {
al.alListenerfv(AL.AL_POSITION, listenerPos, 0);
al.alListenerfv(AL.AL_VELOCITY, listenerVel, 0);
al.alListenerfv(AL.AL_ORIENTATION, listenerOri, 0);
}
static void killALData() {
for (Iterator iter = sources.iterator(); iter.hasNext(); ) {
al.alDeleteSources(1, new int[] { ((Integer)iter.next()).intValue() }, 0);
}
sources.clear();
al.alDeleteBuffers(NUM_BUFFERS, buffers, 0);
exitOpenAL();
}
static boolean initialized = false;
static void initialize() {
if (initialized)
return;
initialized = true;
try {
initOpenAL();
} catch (ALException e) {
e.printStackTrace();
System.exit(1);
}
if (loadALData() == AL.AL_FALSE)
System.exit(1);
setListenerValues();
}
private static void addButton(JFrame frame, String text, final int whichSound) {
JButton button = new JButton(text);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
initialize();
addSource(whichSound);
}
});
frame.getContentPane().add(button);
}
public static void main(String[] args) {
boolean gui = false;
for (int i = 0; i < args.length; i++) {
if (args[i].equals("-gui"))
gui = true;
}
if (gui) {
JFrame frame = new JFrame("Sources Sharing Buffers - DevMaster OpenAL Lesson 5");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new GridLayout(7, 1));
addButton(frame, "Add Water Drop", WATERDROP);
addButton(frame, "Add Thunder", THUNDER);
addButton(frame, "Add Stream", STREAM);
addButton(frame, "Add Rain", RAIN);
addButton(frame, "Add Ocean", OCEAN);
addButton(frame, "Add Chimes", CHIMES);
JButton button = new JButton("Quit");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
frame.getContentPane().add(button);
frame.pack();
frame.setVisible(true);
} else {
initialize();
char[] c = new char[1];
while(c[0] != 'q') {
try {
BufferedReader buf =
new BufferedReader(new InputStreamReader(System.in));
System.out.println("Press a key and hit ENTER: \n" +
"\t'w' for Water Drop\n" +
"\t't' for Thunder\n" +
"\t's' for Stream\n" +
"\t'r' for Rain\n" +
"\t'o' for Ocean\n" +
"\t'c' for Chimes\n" +
"\n'q' to Quit\n");
buf.read(c);
switch(c[0]) {
case 'w': addSource(WATERDROP); break;
case 't': addSource(THUNDER); break;
case 's': addSource(STREAM); break;
case 'r': addSource(RAIN); break;
case 'o': addSource(OCEAN); break;
case 'c': addSource(CHIMES); break;
}
} catch (IOException e) {
killALData();
System.exit(1);
}
}
killALData();
}
}
}