0001: /*
0002: * $RCSfile: JOALMixer.java,v $
0003: *
0004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * Redistribution and use in source and binary forms, with or without
0007: * modification, are permitted provided that the following conditions
0008: * are met:
0009: *
0010: * - Redistribution of source code must retain the above copyright
0011: * notice, this list of conditions and the following disclaimer.
0012: *
0013: * - Redistribution in binary form must reproduce the above copyright
0014: * notice, this list of conditions and the following disclaimer in
0015: * the documentation and/or other materials provided with the
0016: * distribution.
0017: *
0018: * Neither the name of Sun Microsystems, Inc. or the names of
0019: * contributors may be used to endorse or promote products derived
0020: * from this software without specific prior written permission.
0021: *
0022: * This software is provided "AS IS," without a warranty of any
0023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
0024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
0025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
0026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
0027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
0028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
0029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
0030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
0031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
0032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
0033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
0034: * POSSIBILITY OF SUCH DAMAGES.
0035: *
0036: * You acknowledge that this software is not designed, licensed or
0037: * intended for use in the design, construction, operation or
0038: * maintenance of any nuclear facility.
0039: *
0040: * $Revision: 1.6 $
0041: * $Date: 2007/07/06 02:28:32 $
0042: * $State: Exp $
0043: */
0044:
0045: package org.jdesktop.j3d.audioengines.joal;
0046:
0047: import java.net.URL;
0048: import java.util.HashMap;
0049: import javax.vecmath.*;
0050: import javax.media.j3d.*;
0051: import com.sun.j3d.audioengines.*;
0052:
0053: import net.java.games.joal.*;
0054: import net.java.games.joal.util.*;
0055:
0056: /**
0057: * This class is a concrete implementation of AudioEngine3DL2 that uses
0058: * the JOAL/OpenAL sound library to provide rendering of the Sound
0059: * nodes in Java3D. <br>
0060: * Notes: <br>
0061: * 1. getChannelsAvailable, getNumberOfChannelsUsed and getTotalChannels
0062: * have not been implemented yet and thus if you try to play more sounds
0063: * than the system has then they will not play. I am still trying to find
0064: * out exactly how to implement these functions, possibly there is no limit
0065: * when rendering sound using software rendering. Also at the moment I think
0066: * I have limited the implementation to 64 sounds. <br>
0067: * 2. This implementation only plays wav files. <br>
0068: * 3. Other functions not implemented have the comment 'NOT IMPLEMENTED' in their
0069: * respective JavaDoc comment, otherwise the function has been implemented. <br>
0070: * 4. Webstart demos are available at http://www.dutchie.net/joal/default.htm
0071: *<br>
0072: * Usage: <br>
0073: * 1. You must have the OpenAL drivers installed on your machine, these can be
0074: * downloaded for Windows, MacOS, Linux at http://www.openal.org/downloads.html <br>
0075: * 2. You must have JOAL installed which can be downloaded from
0076: * https://joal.dev.java.net/ . This includes joal.zip and the native dll/so for
0077: * your selected platform. <br>
0078: * 3. To use in your application you simply use: <br>
0079: * java -Dj3d.audiodevice=org.jdesktop.j3d.audioengines.joal.JOALMixer [your_application_class]
0080: * and call viewer.createAudioDevice(); as normal.
0081: *
0082: * @author David Grace (dave@dutchie.net)
0083: */
0084: public class JOALMixer extends AudioEngine3DL2 implements AudioDevice,
0085: AudioDevice3D, AudioDevice3DL2 {
0086:
0087: //Debug boolean
0088: private static boolean debug = true;
0089: private static boolean debugVersion = true;
0090: private static boolean debugView = false;
0091: private static boolean debugPrepareSound = true;
0092: private static boolean debugGetTotalChannels = false;
0093: private static boolean debugSampleDuration = false;
0094:
0095: private static boolean debugVelocity = false;
0096:
0097: private static boolean debugPosition = false;
0098: private static boolean debugDirection = false;
0099: private static boolean debugDistanceGain = false;
0100: private static boolean debugGain = false;
0101: private static boolean debugLoopCount = false;
0102: private static boolean debugMute = true;
0103: private static boolean debugUnmute = true;
0104: private static boolean debugStart = true;
0105: private static boolean debugStartTime = true;
0106: private static boolean debugStop = false;
0107: private static boolean debugClearSound = true;
0108:
0109: //Dictates whether or not buffers are shared between samples
0110: private boolean shareBuffer = true;
0111: private HashMap<Object, int[]> sharedBuffers = new HashMap<Object, int[]>();
0112:
0113: private boolean calculateDopplerEffect = false;
0114:
0115: // Determines method to call for added or setting sound into ArrayList
0116: static final int ADD_TO_LIST = 1;
0117: static final int SET_INTO_LIST = 2;
0118:
0119: //AL for access to JOAL
0120: static AL al;
0121: static ALC alc;
0122:
0123: //Temp arrays for passing data from Java to JOAL
0124: private float[] singleArray = new float[1];
0125: private float[] tripleArray = new float[3];
0126:
0127: //Java3D View data
0128: private View reference;
0129: private Transform3D transform = new Transform3D();
0130: private float[] position = new float[3];
0131: private float[] lastPosition = new float[3];
0132: private Vector3f positionVector = new Vector3f();
0133: //private Vector3f lastPositionVector = new Vector3f();
0134: private Vector3f viewVector = new Vector3f(0, 0, -1);
0135: private Vector3f upVector = new Vector3f(0, 1, 0);
0136:
0137: //JOAL listener data
0138:
0139: private float[] velocity = { 0.0f, 0.0f, 0.0f };
0140: private float[] noVelocity = { 0.0f, 0.0f, 0.0f };
0141: private float[] orientation = { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f };
0142:
0143: private long timeOfThisViewUpdate = -1;
0144: private long timeSinceLastViewUpdate = -1;
0145: private float timeSinceLastViewUpdateInSeconds = -1;
0146: private long timeOfLastViewUpdate = -1;
0147:
0148: /** Creates a new instance of JOALMixer */
0149: public JOALMixer(PhysicalEnvironment physicalEnvironment) {
0150: super (physicalEnvironment);
0151: if (debug)
0152: System.out.println("JOALMixer - constructor...");
0153: //initialize();
0154: //if (debug & debugVersion) System.out.println("JOAL - AL_DOPPLER_FACTOR: " + al.alGetFloat(AL.AL_DOPPLER_FACTOR));
0155: //if (debug & debugVersion) System.out.println("JOAL - AL_SPEED_OF_SOUND: " + al.alGetFloat(AL.AL_SPEED_OF_SOUND));
0156: //if (debug & debugVersion) System.out.println("JOAL - AL_DISTANCE_MODEL: " + al.alGetInteger(AL.AL_DISTANCE_MODEL));
0157: }
0158:
0159: /**
0160: * Set overall gain control of all sounds playing on the audio device.
0161: * @param scaleFactor scale factor applied to calculated amplitudes for
0162: * all sounds playing on this device
0163: */
0164: public void setGain(float scaleFactor) {
0165: singleArray[0] = scaleFactor;
0166: al.alListenerfv(AL.AL_GAIN, singleArray, 0);
0167: }
0168:
0169: /** NOT IMPLEMENTED <br>
0170: * Resumes audio device engine (if previously paused) without
0171: * reinitializing the device.
0172: * Causes all paused cached sounds to be resumed and all streaming
0173: * sounds restarted.
0174: */
0175: public void resume() {
0176:
0177: }
0178:
0179: /** NOT IMPLEMENTED <br>
0180: * Pauses audio device engine without closing the device and associated
0181: * threads.
0182: * Causes all cached sounds to be paused and all streaming sounds to be
0183: * stopped.
0184: */
0185: public void pause() {
0186:
0187: }
0188:
0189: /**
0190: * Save a reference to the current View object.
0191: * @param reference to current view object
0192: */
0193: public void setView(View reference) {
0194: if (debug && debugView)
0195: System.out.println("JOALMixer - setView...");
0196: if (reference.getAllCanvas3Ds().hasMoreElements()) {
0197: reference.getUserHeadToVworld(transform);
0198: transform.get(positionVector);
0199: position[0] = positionVector.x;
0200: position[1] = positionVector.y;
0201: position[2] = positionVector.z;
0202: al.alListenerfv(AL.AL_POSITION, position, 0);
0203:
0204: //Update velocity information
0205: if (timeOfLastViewUpdate == -1) {
0206: timeOfLastViewUpdate = System.nanoTime();
0207: lastPosition[0] = positionVector.x;
0208: lastPosition[1] = positionVector.y;
0209: lastPosition[2] = positionVector.z;
0210: } else {
0211: timeOfThisViewUpdate = System.nanoTime();
0212: timeSinceLastViewUpdate = timeOfLastViewUpdate
0213: - timeOfThisViewUpdate;
0214: timeOfLastViewUpdate = timeOfThisViewUpdate;
0215:
0216: if (calculateDopplerEffect) {
0217: timeSinceLastViewUpdateInSeconds = timeSinceLastViewUpdate / 1000000;
0218: velocity[0] = (lastPosition[0] - position[0])
0219: / timeSinceLastViewUpdateInSeconds;
0220: velocity[1] = (lastPosition[1] - position[1])
0221: / timeSinceLastViewUpdateInSeconds;
0222: velocity[2] = (lastPosition[2] - position[2])
0223: / timeSinceLastViewUpdateInSeconds;
0224: al.alListenerfv(AL.AL_VELOCITY, velocity, 0);
0225: if (debug & debugVelocity)
0226: System.out.println("JOALMixer - velocity: "
0227: + velocity[0] + ", " + velocity[1]
0228: + ", " + velocity[2]);
0229: } else {
0230: al.alListenerfv(AL.AL_VELOCITY, noVelocity, 0);
0231: }
0232:
0233: lastPosition[0] = positionVector.x;
0234: lastPosition[1] = positionVector.y;
0235: lastPosition[2] = positionVector.z;
0236: }
0237: //Vector3f viewVector= new Vector3f(0, 0, -1);
0238: //Vector3f upVector = new Vector3f(0, 1, 0);
0239: viewVector.set(0, 0, -1);
0240: upVector.set(0, 1, 0);
0241: //get viewVector
0242: transform.transform(viewVector);
0243:
0244: //get upVector
0245: transform.transform(upVector);
0246: orientation[0] = viewVector.x;
0247: orientation[1] = viewVector.y;
0248: orientation[2] = viewVector.z;
0249: orientation[3] = upVector.x;
0250: orientation[4] = upVector.y;
0251: orientation[5] = upVector.z;
0252:
0253: al.alListenerfv(AL.AL_ORIENTATION, orientation, 0);
0254: }
0255: super .setView(reference);
0256: }
0257:
0258: /**
0259: * Prepare Sound in device <br>
0260: * Makes sound assessible to device - in this case attempts to load sound
0261: * Stores sound type and data.
0262: * @param soundType denotes type of sound: Background, Point or Cone
0263: * @param soundData descrition of sound source data
0264: * @return index into sample vector of Sample object for sound
0265: */
0266: public int prepareSound(int soundType, MediaContainer soundData) {
0267: if (debug && debugPrepareSound) {
0268: if (soundData.getURLObject() != null) {
0269: System.out.println("JOALMixer - prepareSound - "
0270: + soundData + " - " + soundData.getURLObject());
0271: } else if (soundData.getURLString() != null) {
0272: System.out.println("JOALMixer - prepareSound - "
0273: + soundData + " - " + soundData.getURLString());
0274: } else
0275: System.out.println("JOALMixer - prepareSound - "
0276: + soundData + " - "
0277: + soundData.getInputStream());
0278: }
0279: int index = JOALSample.NULL_SAMPLE;
0280: int methodType = ADD_TO_LIST;
0281:
0282: if (soundData == null)
0283: return JOALSample.NULL_SAMPLE;
0284: synchronized (samples) {
0285: int samplesSize = samples.size();
0286: index = samplesSize;
0287: samples.ensureCapacity(index + 1);
0288:
0289: JOALSample joalSample = new JOALSample();
0290: boolean error = true;
0291:
0292: //Code added here to address bug id 500 - JOALMixer should share buffers.
0293: //If the MediaContainer has a URLObject and has been loaded before
0294: //then the same buffer will be used.
0295: //As yet I am unable to determine when a buffer should be removed
0296: //from the HashMap to release the buffer from memory
0297:
0298: if (shareBuffer) {
0299: if (soundData.getURLObject() != null) {
0300: if (sharedBuffers.containsKey(soundData
0301: .getURLObject())) {
0302: error = joalSample.load(al, sharedBuffers
0303: .get(soundData.getURLObject()),
0304: soundType);
0305: } else {
0306: error = joalSample.load(al, soundData,
0307: soundType);
0308: sharedBuffers.put(soundData.getURLObject(),
0309: joalSample.getBuffer());
0310: }
0311: } else if (soundData.getURLString() != null) {
0312: if (sharedBuffers.containsKey(soundData
0313: .getURLString())) {
0314: error = joalSample.load(al, sharedBuffers
0315: .get(soundData.getURLString()),
0316: soundType);
0317: } else {
0318: error = joalSample.load(al, soundData,
0319: soundType);
0320: sharedBuffers.put(soundData.getURLString(),
0321: joalSample.getBuffer());
0322: }
0323: } else {
0324: if (sharedBuffers.containsKey(soundData
0325: .getInputStream())) {
0326: error = joalSample.load(al, sharedBuffers
0327: .get(soundData.getInputStream()),
0328: soundType);
0329: } else {
0330: error = joalSample.load(al, soundData,
0331: soundType);
0332: sharedBuffers.put(soundData.getInputStream(),
0333: joalSample.getBuffer());
0334: }
0335: }
0336:
0337: } else {
0338: error = joalSample.load(al, soundData, soundType);
0339: }
0340:
0341: if (error)
0342: return JOALSample.NULL_SAMPLE;
0343: if (methodType == SET_INTO_LIST)
0344: samples.set(index, joalSample);
0345: else
0346: samples.add(index, joalSample);
0347: if (debug)
0348: System.out
0349: .println("JOALMixer - prepareSound - return: "
0350: + index);
0351: return index;
0352: }
0353: }
0354:
0355: /**
0356: * Clear Sound.
0357: * Removes/clears associated sound data with this sound source node
0358: * @param index device specific reference number to device driver sample
0359: */
0360: public void clearSound(int index) {
0361: if (debug && debugClearSound)
0362: System.out.println("JOALMixer - clearSound " + index);
0363: Sample sample = null;
0364: if ((sample = getSample(index)) == null)
0365: return;
0366: sample.clear();
0367: synchronized (samples) {
0368: samples.set(index, null);
0369: }
0370: }
0371:
0372: /**
0373: * Get length of time a sample would play if allowed to play to completion.
0374: * @param index device specific reference number to device driver sample
0375: * @return length of sample in milliseconds
0376: */
0377: public long getSampleDuration(int index) {
0378: if (debug && debugSampleDuration)
0379: System.out.println("JOALMixer - getSampleDuration for "
0380: + index);
0381: return super .getSampleDuration(index);
0382: }
0383:
0384: /** NOT IMPLEMENTED <br>
0385: * Get number of channels used by a particular sample on the audio device.
0386: * @param index device specific reference number to device driver sample
0387: * @return number of channels currently being used by this sample.
0388: */
0389: public int getNumberOfChannelsUsed(int index) {
0390: //if (debug) System.out.println("JOALMixer - getNumberOfChannelsUsed...");
0391: return super .getNumberOfChannelsUsed(index);
0392: }
0393:
0394: /** NOT IMPLEMENTED <br>
0395: * Get number of channels that would be used by a particular sample on
0396: * the audio device given the mute flag passed in as a parameter.
0397: * @param index device specific reference number to device driver sample
0398: * @param muteFlag denotes the mute state to assume while executing this
0399: * query. This mute value does not have to match the current mute state
0400: * of the sample.
0401: * @return number of channels that would be used by this sample if it
0402: * were playing.
0403: */
0404: public int getNumberOfChannelsUsed(int index, boolean muteFlag) {
0405: //if (debug) System.out.println("JOALMixer - getNumberOfChannelsUsed...boolean");
0406: return 1;
0407: }
0408:
0409: /**
0410: * Start sample playing on audio device
0411: * @param index device specific reference number to device driver sample
0412: * @return status: < 0 denotes an error
0413: */
0414: public int startSample(int index) {
0415: if (debug & debugStart)
0416: System.out.println("JOALMixer - start..." + index);
0417: //super.startSample(index);
0418: JOALSample s = (JOALSample) getSample(index);
0419: if (s == null)
0420: return -1;
0421: else
0422: return s.startSample();
0423: }
0424:
0425: /** NOT IMPLEMENTED <br>
0426: * Get time this sample begun playing on the audio device.
0427: * @param index device specific reference number to device driver sample
0428: * @return system clock time sample started
0429: */
0430: public long getStartTime(int index) {
0431: if (debug && debugStartTime)
0432: System.out.println("JOALMixer - getStartTime for " + index);
0433: return -1;
0434: }
0435:
0436: /**
0437: * Stop sample playing on audio device
0438: * @param index device specific reference number to device driver sample
0439: * @return status: < 0 denotes an error
0440: */
0441: public int stopSample(int index) {
0442: if (debug & debugStop)
0443: System.out.println("JOALMixer - stopSample " + index);
0444: JOALSample s = (JOALSample) getSample(index);
0445: if (s == null)
0446: return -1;
0447: else
0448: return s.stopSample();
0449: }
0450:
0451: /**
0452: * Set gain scale factor applied to sample.
0453: * @param index device specific reference number to device driver sample
0454: * @param scaleFactor floating point multiplier applied to sample amplitude
0455: */
0456: public void setSampleGain(int index, float scaleFactor) {
0457: if (debug & debugGain)
0458: System.out.println("JOALMixer - setSampleGain for " + index
0459: + " to " + scaleFactor);
0460: JOALSample s = (JOALSample) getSample(index);
0461: if (s == null)
0462: return;
0463: else
0464: s.setGain(scaleFactor);
0465: }
0466:
0467: /** NOT IMPLEMENTED COMPLETELY <br>
0468: * Set number of times sample is looped <br>
0469: * Works for values 0 (no loop) and (-1) infinite loop but not
0470: * for a fix number of loops (>1) <br>
0471: * @param index device specific reference number to device driver sample
0472: * @param count number of times sample is repeated
0473: */
0474: public void setLoop(int index, int count) {
0475: if (debug & debugLoopCount)
0476: System.out.println("JOALMixer - setLoop for " + index
0477: + " to " + count);
0478: super .setLoop(index, count);
0479: }
0480:
0481: /** DOES NOTHING - does not need to do anything special for JOAL<br>
0482: * Set the transform for local to virtual world coordinate space
0483: * @param index device specific reference number to device driver sample
0484: * @param trans is a reference to virtual world composite transform
0485: */
0486: public void setVworldXfrm(int index, Transform3D trans) {
0487: if (debug)
0488: System.out.println("JOALMixer - setVworldXfrm...");
0489: super .setVworldXfrm(index, trans);
0490: }
0491:
0492: /**
0493: * Set location of sample.
0494: * @param index device specific reference number to device driver sample
0495: * @param position point location in virtual world coordinate of sample
0496: */
0497: public void setPosition(int index, Point3d position) {
0498: if (debug & debugPosition)
0499: System.out.println("JOALMixer - setPosition for " + index
0500: + " to " + position);
0501: super .setPosition(index, position);
0502: }
0503:
0504: /**
0505: * Set elliptical distance attenuation arrays applied to sample amplitude<br>
0506: * OPENAL/JOAL calculates the distance attenuation using its default model
0507: * which is the inverse distance clamped model (equivalent to the IASIG I3DL2
0508: * distance model) <br>
0509: * This is: <br>
0510: * distance = max(distance, AL_REFERENCE_DISTANCE); <br>
0511: * distance = max(distance, AL_MAX_DISTANCE); <br>
0512: * gain = AL_REFERENCE_DISTANCE / (AL_REFERENCE_DISTANCE +
0513: * AL_ROLLOFF_FACTOR * (distance - AL_REFERENCE_DISTANCE)); <br>
0514: * This function calculates the AL_REFERENCE_DISTANCE, AL_MAX_DISTANCE and
0515: * AL_ROLLOFF_FACTOR from the given distance attenuation data from Java3D. <br>
0516: * @param index device specific reference number to device driver sample
0517: * @param frontDistance defines an array of distance along the position axis
0518: * thru which ellipses pass
0519: * @param frontAttenuationScaleFactor gain scale factors
0520: * @param backDistance defines an array of distance along the negative axis
0521: * thru which ellipses pass
0522: * @param backAttenuationScaleFactor gain scale factors
0523: */
0524: public void setDistanceGain(int index, double[] frontDistance,
0525: float[] frontAttenuationScaleFactor, double[] backDistance,
0526: float[] backAttenuationScaleFactor) {
0527: if (debug & debugDistanceGain)
0528: System.out.println("JOALMixer - setDistanceGain for "
0529: + index + " with " + frontDistance + ", "
0530: + frontAttenuationScaleFactor + ", " + backDistance
0531: + ", " + backAttenuationScaleFactor);
0532: super .setDistanceGain(index, frontDistance,
0533: frontAttenuationScaleFactor, backDistance,
0534: backAttenuationScaleFactor);
0535: }
0536:
0537: /**
0538: * Set direction vector of sample.
0539: * @param index device specific reference number to device driver sample
0540: * @param direction vector in virtual world coordinate.
0541: */
0542: public void setDirection(int index, Vector3d direction) {
0543: if (debug & debugDirection)
0544: System.out.println("JOALMixer - setDirection for " + index
0545: + " to " + direction);
0546: super .setDirection(index, direction);
0547: }
0548:
0549: /**
0550: * Set angular attenuation arrays affecting angular amplitude attenuation
0551: * and angular distance filtering <br>
0552: * Angular attenuation in OpenAL/JOAL is determined by AL_CONE_INNER_ANGLE,
0553: * AL_CONE_OUTER_ANGLE and AL_CONE_OUTER_GAIN <br>
0554: * The region inside and AL_CONE_OUTER_ANGLE
0555: * has its gain unchanged (AL_GAIN), the region inside AL_CONE_INNER_ANGLE and AL_CONE_OUTER_ANGLE
0556: * has its gain between AL_GAIN and AL_CONE_OUTER_GAIN, and the region outside
0557: * AL_CONE_OUTER_ANGLE has gain of AL_CONE_OUTER_GAIN <br>
0558: * This function calculates the AL_CONE_INNER_ANGLE, AL_CONE_OUTER_ANGLE and
0559: * AL_CONE_OUTER_GAIN from the given angular attenuation data from Java3D. <br>
0560: * @param index device specific reference number to device driver sample
0561: * @param filterType denotes type of filtering (on no filtering) applied
0562: * to sample.
0563: * @param angle array containing angular distances from sound axis
0564: * @param attenuationScaleFactor array containing gain scale factor
0565: * @param filterCutoff array containing filter cutoff frequencies.
0566: * The filter values for each tuples can be set to Sound.NO_FILTER.
0567: */
0568: public void setAngularAttenuation(int index, int filterType,
0569: double[] angle, float[] attenuationScaleFactor,
0570: float[] filterCutoff) {
0571: if (debug)
0572: System.out.println("JOALMixer - setAngularAttenuation...");
0573: super .setAngularAttenuation(index, filterType, angle,
0574: attenuationScaleFactor, filterCutoff);
0575: }
0576:
0577: /** NOT IMPLEMENTED <br>
0578: * Set rolloff value for current aural attribute applied to all samples.
0579: * @param rolloff scale factor applied to standard speed of sound.
0580: */
0581: public void setRolloff(float rolloff) {
0582: if (debug)
0583: System.out.println("JOALMixer - setRolloff...");
0584: }
0585:
0586: /** NOT IMPLEMENTED <br>
0587: * Set reverberation surface reflection coefficient value for current aural
0588: * attribute applied to all samples.
0589: * @param coefficient applied to amplitude of reverbation added at each
0590: * iteration of reverb processing.
0591: */
0592: public void setReflectionCoefficient(float coefficient) {
0593: if (debug)
0594: System.out
0595: .println("JOALMixer - setReflectionCoefficient...");
0596: }
0597:
0598: /** NOT IMPLEMENTED <br>
0599: * Set reverberation delay time for current aural attribute applied to
0600: * all samples.
0601: * @param reverbDelay amount of time in millisecond between each
0602: * iteration of reverb processing.
0603: */
0604: public void setReverbDelay(float reverbDelay) {
0605: if (debug)
0606: System.out.println("JOALMixer - setReverbDelay...");
0607: }
0608:
0609: /** NOT IMPLEMENTED <br>
0610: * Set reverberation order for current aural attribute applied to all
0611: * samples.
0612: * @param reverbOrder number of times reverb process loop is iterated.
0613: */
0614: public void setReverbOrder(int reverbOrder) {
0615: if (debug)
0616: System.out.println("JOALMixer - setReverbOrder...");
0617: }
0618:
0619: /** NOT IMPLEMENTED <br>
0620: * Set distance filter for current aural attribute applied to all samples.
0621: * @param filterType denotes type of filtering (on no filtering) applied
0622: * to all sample based on distance between listener and sound.
0623: * @param dist is an attenuation array of distance and low-pass filter values.
0624: */
0625: public void setDistanceFilter(int filterType, double[] distance,
0626: float[] dist) {
0627: if (debug)
0628: System.out.println("JOALMixer - setDistanceFilter...");
0629: }
0630:
0631: /** NOT IMPLEMENTED <br>
0632: * Set frequency scale factor for current aural attribute applied to all
0633: * samples.
0634: * @param frequencyScaleFactor frequency scale factor applied to samples normal
0635: * playback rate.
0636: */
0637: public void setFrequencyScaleFactor(float frequencyScaleFactor) {
0638: if (debug)
0639: System.out
0640: .println("JOALMixer - setFrequencyScaleFactor to "
0641: + frequencyScaleFactor);
0642: }
0643:
0644: /** NOT IMPLEMENTED <br>
0645: * Set velocity scale factor for current aural attribute applied to all
0646: * samples when Doppler is calculated.
0647: * @param velocityScaleFactor scale factor applied to postional samples'
0648: * listener-to-soundSource velocity.
0649: * playback rate.
0650: */
0651: public void setVelocityScaleFactor(float velocityScaleFactor) {
0652: if (debug)
0653: System.out.println("JOALMixer - setVelocityScaleFactor to "
0654: + velocityScaleFactor);
0655: super .setVelocityScaleFactor(velocityScaleFactor);
0656: }
0657:
0658: /**
0659: * Mute sample.
0660: * @param index device specific reference number to device driver sample
0661: */
0662: public void muteSample(int index) {
0663: if (debug && debugMute)
0664: System.out.println("JOALMixer - muteSample " + index);
0665: Sample sample = (Sample) getSample(index);
0666: if (sample != null)
0667: sample.setMuteFlag(true);
0668: }
0669:
0670: /**
0671: * Unmute sample.
0672: * @param index device specific reference number to device driver sample
0673: */
0674: public void unmuteSample(int index) {
0675: if (debug && debugUnmute)
0676: System.out.println("JOALMixer - unmuteSample for " + index);
0677: Sample sample = (Sample) getSample(index);
0678: if (sample != null)
0679: sample.setMuteFlag(false);
0680: }
0681:
0682: /**
0683: * Pause sample.
0684: * @param index device specific reference number to device driver sample
0685: */
0686: public void pauseSample(int index) {
0687: if (debug)
0688: System.out.println("JOALMixer - pauseSample for " + index);
0689: al.alSourcePause(index);
0690: }
0691:
0692: /**
0693: * Unpause sample.
0694: * @param index device specific reference number to device driver sample
0695: */
0696: public void unpauseSample(int index) {
0697: if (debug)
0698: System.out
0699: .println("JOALMixer - unpauseSample for " + index);
0700: al.alSourcePlay(index);
0701: }
0702:
0703: /** DOES NOTHING - not really needed when using JOAL <br>
0704: * Update sample
0705: * Implies that some parameters affecting rendering have been modified.
0706: * @param index device specific reference number to device driver sample
0707: */
0708: public void updateSample(int index) {
0709: //if (debug) System.out.println("JOALMixer - updateSample " + index);
0710: }
0711:
0712: /**
0713: * Code to initialize the device
0714: * @return flag: true is initialized sucessfully, false if error
0715: */
0716: public boolean initialize() {
0717: if (debug)
0718: System.out.println("JOALMixer - initialize...");
0719:
0720: try {
0721: ALut.alutInit();
0722: al = ALFactory.getAL();
0723: al.alDistanceModel(AL.AL_INVERSE_DISTANCE);
0724: //if (debug & debugVersion) System.out.println("JOALMixer - JOAL version: " + Version.getVersion());
0725: if (debug & debugVersion)
0726: System.out.println("JOALMixer - JOAL renderer: "
0727: + al.alGetString(AL.AL_RENDERER));
0728: if (debug & debugVersion)
0729: System.out.println("JOALMixer - JOAL vendor: "
0730: + al.alGetString(AL.AL_VENDOR));
0731: if (debug & debugVersion)
0732: System.out.println("JOALMixer - JOAL extension: "
0733: + al.alGetString(AL.AL_EXTENSIONS));
0734:
0735: } catch (ALException e) {
0736: e.printStackTrace();
0737: if (debug)
0738: System.out
0739: .println("JOALMixer - initialize failed - Error initializing JOALMixer, code: "
0740: + al.alGetError());
0741: return false;
0742: }
0743: if (debug)
0744: System.out.println("JOALMixer - initialize success.");
0745: return true;
0746: }
0747:
0748: /** NOT IMPLEMENTED <br>
0749: * Code to close the device
0750: * @return flag: true is closed sucessfully, false if error
0751: */
0752: public boolean close() {
0753: if (debug)
0754: System.out.println("JOALMixer - close...");
0755: //Not sure if all the samples should be clear(ed), if yes then uncomment
0756: /*
0757: int index = 0;
0758: synchronized(samples) {
0759: for (Object s:samples){
0760: Sample sample = (Sample) s;
0761: if ( (sample = getSample(index)) == null){
0762:
0763: } else {
0764: sample.clear();
0765: samples.set(index, null);
0766: }
0767: }
0768: }
0769: return true;
0770: */
0771:
0772: return false;
0773: }
0774:
0775: /**
0776: * Set Type of Audio Playback physical transducer(s) sound is output to <br>
0777: * Valid types are HEADPHONE, MONO_SPEAKER, STEREO_SPEAKERS
0778: * @param type of audio output device
0779: */
0780: public void setAudioPlaybackType(int type) {
0781: if (debug)
0782: System.out.println("JOALMixer - setAudioPlaybackType to "
0783: + type);
0784: super .setAudioPlaybackType(type);
0785: }
0786:
0787: /**
0788: * Get Type of Audio Playback Output Device
0789: * returns audio playback type to which sound is currently output
0790: */
0791: public int getAudioPlaybackType() {
0792: if (debug)
0793: System.out.println("JOALMixer - getAudioPlaybackType...");
0794: return super .getAudioPlaybackType();
0795: }
0796:
0797: /**
0798: * Set Distance from the Center Ear to a Speaker
0799: * @param distance from the center ear and to the speaker
0800: */
0801: public void setCenterEarToSpeaker(float distance) {
0802: if (debug)
0803: System.out.println("JOALMixer - setCenterEarToSpeaker to "
0804: + distance);
0805: super .setCenterEarToSpeaker(distance);
0806: }
0807:
0808: /**
0809: * Get Distance from Ear to Speaker
0810: * returns value set as distance from listener's ear to speaker
0811: */
0812: public float getCenterEarToSpeaker() {
0813: if (debug)
0814: System.out.println("JOALMixer - getCenterEarToSpeaker...");
0815: return super .getCenterEarToSpeaker();
0816: }
0817:
0818: /**
0819: * Set Angle Offset To Speaker
0820: * @param angle in radian between head coordinate Z axis and vector to speaker
0821: */
0822: public void setAngleOffsetToSpeaker(float angle) {
0823: if (debug)
0824: System.out.println("JOALMixer - setAngleOffsetToSpeaker "
0825: + angle);
0826: super .setAngleOffsetToSpeaker(angle);
0827: }
0828:
0829: /**
0830: * Get Angle Offset To Speaker
0831: * returns value set as angle between vector to speaker and Z head axis
0832: */
0833: public float getAngleOffsetToSpeaker() {
0834: if (debug)
0835: System.out
0836: .println("JOALMixer - getAngleOffsetToSpeaker...");
0837: return super .getAngleOffsetToSpeaker();
0838: }
0839:
0840: /** NOT IMPLEMENTED <br>
0841: * Query total number of channels available for sound rendering
0842: * for this audio device.
0843: * returns number of maximum sound channels you can run with this
0844: * library/device-driver.
0845: */
0846: public int getTotalChannels() {
0847: if (debug && debugGetTotalChannels)
0848: System.out.println("JOALMixer - getTotalChannels...");
0849: return 64;
0850: }
0851:
0852: /** NOT IMPLEMENTED <br>
0853: * Query number of channels currently available for use by the
0854: * returns number of sound channels currently available (number
0855: * not being used by active sounds).
0856: */
0857: public int getChannelsAvailable() {
0858: if (debug)
0859: System.out.println("JOALMixer - getChannelsAvailable...");
0860: return 8;
0861: }
0862:
0863: /**
0864: * Query number of channels that would be used to render a particular
0865: * sound node.
0866: * @param sound refenence to sound node that query to be performed on
0867: * returns number of sound channels used by a specific Sound node
0868: * @deprecated This method is now part of the Sound class
0869: */
0870: public int getChannelsUsedForSound(Sound sound) {
0871: if (debug)
0872: System.out
0873: .println("JOALMixer - getChannelsUsedForSound...");
0874: return super .getChannelsUsedForSound(sound);
0875: }
0876:
0877: /**
0878: * Set scale factor applied to sample playback rate for a particular sound
0879: * associated with the audio device <br>
0880: * Changing the device sample rate affects both the pitch and speed.
0881: * This scale factor is applied to ALL sound types <br>
0882: * Changes (scales) the playback rate of a sound independent of
0883: * Doppler rate changes.
0884: * @param index device specific reference to device driver sample
0885: * @param scaleFactor non-negative factor applied to calculated
0886: * amplitudes for all sounds playing on this device
0887: * @see Sound#setRateScaleFactor
0888: */
0889: public void setRateScaleFactor(int index, float scaleFactor) {
0890: JOALSample s = (JOALSample) getSample(index);
0891: if (s == null)
0892: return;
0893: else
0894: s.setRateScaleFactor(scaleFactor);
0895: }
0896:
0897: /** NOT IMPLEMENTED <br>
0898: * Set late reflection (referred to as 'reverb') attenuation.
0899: * This scale factor is applied to iterative, indistinguishable
0900: * late reflections that constitute the tail of reverberated sound in
0901: * the aural environment <br>
0902: * This parameter, along with the early reflection coefficient, defines
0903: * the reflective/absorptive characteristic of the surfaces in the
0904: * current listening region.
0905: * @param coefficient late reflection attenuation factor
0906: * @see AuralAttributes#setReverbCoefficient
0907: */
0908: public void setReverbCoefficient(float coefficient) {
0909: }
0910:
0911: /** NOT IMPLEMENTED
0912: * Sets the early reflection delay time <br>
0913: * In this form, the parameter specifies the delay time between each order
0914: * of reflection (while reverberation is being rendered) explicitly given
0915: * in milliseconds.
0916: * @param reflectionDelay time between each order of early reflection
0917: * @see AuralAttributes#setReflectionDelay
0918: */
0919: public void setReflectionDelay(float reflectionDelay) {
0920: }
0921:
0922: /** NOT IMPLEMENTED <br>
0923: * Set reverb decay time <br>
0924: * Defines the reverberation decay curve.
0925: * @param time decay time in milliseconds
0926: * @see AuralAttributes#setDecayTime
0927: */
0928: public void setDecayTime(float time) {
0929: }
0930:
0931: /** NOT IMPLEMENTED <br>
0932: * Set reverb decay filter <br>
0933: * This provides for frequencies above the given cutoff frequency to be
0934: * attenuated during reverb decay at a different rate than frequencies
0935: * below this value <br>
0936: * Thus, defining a different reverb decay curve for
0937: * frequencies above the cutoff value.
0938: * @param frequencyCutoff value of frequencies in Hertz above which a
0939: * low-pass filter is applied.
0940: * @see AuralAttributes#setDecayFilter
0941: */
0942: public void setDecayFilter(float frequencyCutoff) {
0943: }
0944:
0945: /** NOT IMPLEMENTED <br>
0946: * Set reverb diffusion <br>
0947: * This defines the echo dispersement (also referred to as 'echo density') <br>
0948: * The value of this reverb parameter is expressed as a percent of the
0949: * audio device's minimum-to-maximum values.
0950: * @param diffusion percentage expressed within the range of 0.0 and 1.0
0951: * @see AuralAttributes#setDiffusion
0952: */
0953: public void setDiffusion(float diffusion) {
0954: }
0955:
0956: /** NOT IMPLEMENTED <br>
0957: * Set reverb density <br>
0958: * This defines the modal density (also referred to as 'spectral
0959: * coloration') <br>
0960: * The value of this parameter is expressed as a percent of the audio
0961: * device's minimum-to-maximum values for this reverb parameter.
0962: * @param density reverb density expressed as a percentage,
0963: * within the range of 0.0 and 1.0
0964: * @see AuralAttributes#setDensity
0965: */
0966: public void setDensity(float density) {
0967: }
0968:
0969: /** NOT IMPLEMENTED <br>
0970: * Set the obstruction gain control <br>
0971: * This method allows for attenuating
0972: * sound waves traveling between the sound source and the listener
0973: * obstructed by objects <br>
0974: * Direct sound signals/waves for obstructed sound
0975: * source are attenuated but not indirect (reflected) waves.
0976: * There is no corresponding Core AuralAttributes method at this time.
0977: * @param index device specific reference to device driver sample
0978: * @param scaleFactor non-negative factor applied to direct sound gain
0979: */
0980: public void setObstructionGain(int index, float scaleFactor) {
0981: }
0982:
0983: /** NOT IMPLEMENTED <br>
0984: * Set the obstruction filter control <br>
0985: * This provides for frequencies above the given cutoff frequency
0986: * to be attenuated, during while the gain of an obstruction signal
0987: * is being calculated, at a different rate than frequencies
0988: * below this value.
0989: * There is no corresponding Core AuralAttributes method at this time.
0990: * @param index device specific reference to device driver sample
0991: * @param frequencyCutoff value of frequencies in Hertz above which a
0992: * low-pass filter is applied.
0993: */
0994: public void setObstructionFilter(int index, float frequencyCutoff) {
0995: }
0996:
0997: /** NOT IMPLEMENTED <br>
0998: * Set the occlusion gain control <br>
0999: * This method allows for attenuating
1000: * sound waves traveling between the sound source and the listener
1001: * occluded by objects <br>
1002: * Both direct and indirect sound signals/waves
1003: * for occluded sound sources are attenuated <br>
1004: * There is no corresponding Core AuralAttributes method at this time.
1005: * @param index device specific reference to device driver sample
1006: * @param scaleFactor non-negative factor applied to direct sound gain
1007: */
1008: public void setOcclusionGain(int index, float scaleFactor) {
1009: }
1010:
1011: /** NOT IMPLEMENTED <br>
1012: * Set the occlusion filter control <br>
1013: * This provides for frequencies above the given cutoff frequency
1014: * to be attenuated, during while the gain of an occluded signal
1015: * is being calculated, at a different rate than frequencies below
1016: * this value <br>
1017: * There is no corresponding Core AuralAttributes method at this time.
1018: * @param index device specific reference to device driver sample
1019: * @param frequencyCutoff value of frequencies in Hertz above which a
1020: * low-pass filter is applied.
1021: */
1022: public void setOcclusionFilter(int index, float frequencyCutoff) {
1023: }
1024:
1025: /** Unused code for more specific initialization of a sound device.
1026: * Maybe useful later if the option of selecting which device
1027: * on the machine is used. At the moment it is the 'default' device
1028: * returned by OpenAL/JOAL that is used.
1029: */
1030: static int initOpenAL() {
1031:
1032: ALCdevice device;
1033: ALCcontext context;
1034: String deviceSpecifier;
1035: String deviceName = "DirectSound3D";
1036:
1037: // Get handle to device.
1038: device = alc.alcOpenDevice(deviceName);
1039:
1040: // Get the device specifier.
1041: deviceSpecifier = alc.alcGetString(device,
1042: ALC.ALC_DEVICE_SPECIFIER);
1043:
1044: System.out.println("Using device " + deviceSpecifier);
1045:
1046: // Create audio context.
1047: context = alc.alcCreateContext(device, null);
1048:
1049: // Set active context.
1050: alc.alcMakeContextCurrent(context);
1051:
1052: // Check for an error.
1053: if (alc.alcGetError(device) != ALC.ALC_NO_ERROR)
1054: return AL.AL_FALSE;
1055:
1056: return AL.AL_TRUE;
1057: }
1058:
1059: /** Unused code for to release resources created with the function above.
1060: * Maybe useful later if the option of selecting which device
1061: * on the machine is used. This would be used to close device.
1062: */
1063: static void exitOpenAL() {
1064: ALCcontext curContext;
1065: ALCdevice curDevice;
1066:
1067: // Get the current context.
1068: curContext = alc.alcGetCurrentContext();
1069:
1070: // Get the device used by that context.
1071: curDevice = alc.alcGetContextsDevice(curContext);
1072:
1073: // Reset the current context to NULL.
1074: alc.alcMakeContextCurrent(null);
1075:
1076: // Release the context and the device.
1077: alc.alcDestroyContext(curContext);
1078: alc.alcCloseDevice(curDevice);
1079: }
1080:
1081: private void calculateOrientation(View view) {
1082: Vector3f viewPosition = new Vector3f();
1083: Vector3f viewVector = new Vector3f(0, 0, -1);
1084: Vector3f upVector = new Vector3f(0, 1, 0);
1085:
1086: Transform3D viewTransform = new Transform3D();
1087: view.getUserHeadToVworld(viewTransform);
1088:
1089: //get position
1090: viewTransform.get(viewPosition);
1091:
1092: //get viewVector
1093: viewTransform.transform(viewVector);
1094:
1095: //get upVector
1096: viewTransform.transform(upVector);
1097:
1098: System.out.println("Position: " + viewPosition);
1099: System.out.println("viewVector: " + viewVector);
1100: System.out.println("upVector: " + upVector);
1101: }
1102:
1103: }
|