com.sun.j3d.audioengines.javasound.JSSample Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java3d-core Show documentation
Show all versions of java3d-core Show documentation
Java3D Core And Java3D Util Libraries
The newest version!
/*
* Copyright (c) 2007 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, licensed or
* intended for use in the design, construction, operation or
* maintenance of any nuclear facility.
*
*/
/*
* Java Sound Sample object
*
* IMPLEMENTATION NOTE: The JavaSoundMixer is incomplete and really needs
* to be rewritten.
*/
package com.sun.j3d.audioengines.javasound;
import java.io.InputStream;
import java.net.URL;
import javax.media.j3d.MediaContainer;
import javax.media.j3d.View;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.DataLine;
import com.sun.j3d.audioengines.AuralParameters;
/**
* The Sample Class extended for Java Sound Mixer specific audio device.
*/
class JSSample extends com.sun.j3d.audioengines.Sample
{
/*
* NOTE: for this device type there is exactly one sample associated
* with each sound.
*/
/**
* Sound Data Types
*
* Samples can be processed as streaming or buffered data.
* Fully spatializing sound sources may require data to be buffered.
*
* Sound data specified as Streaming is not copied by the AudioDevice
* driver implementation. It is up the application to ensure that
* this data is continuously accessible during sound rendering.
* Futhermore, full sound spatialization may not be possible, for
* all AudioDevice implementations on unbuffered sound data.
*/
static final int STREAMING_AUDIO_DATA = 1;
/**
* Sound data specified as Buffered is copied by the AudioDevice
* driver implementation.
*/
static final int BUFFERED_AUDIO_DATA = 2;
/**
* MIDI data
* TODO: differentiate between STREAMING and BUFFERED MIDI data
* right now all MIDI data is buffered
*/
static final int STREAMING_MIDI_DATA = 3;
static final int BUFFERED_MIDI_DATA = 3;
static final int UNSUPPORTED_DATA_TYPE = -1;
static final int NULL_SAMPLE = -1;
/**
* sound data types: BUFFERED (cached) or STREAMING (non-cached)
*/
int dataType = BUFFERED_AUDIO_DATA;
JSChannel channel = null;
/**
* Offset pointer within currently playing sample data
*/
long dataOffset = 0;
/*
* Maintain continuously playing silent sound sources.
*/
long timeDeactivated = 0;
long positionDeactivated = 0;
long sampleLength = 0;
long loopStartOffset = 0; // for most this will be 0
long loopLength = 0; // for most this is end sample - sampleLength
long attackLength = 0; // portion of sample before loop section
long releaseLength = 0; // portion of sample after loop section
float rateRatio = 1.0f;
float currentRateRatio = -1.0f; // last actual rate ratio send to device
float targetRateRatio = -1.0f;
boolean rampRateFlag = false;
public JSSample() {
super();
if (debugFlag)
debugPrintln("JSSample constructor");
}
// the only public methods are those declared in the audioengines
// package as public
/*
* This excutes code necessary to set current fields to their current
* correct values before JavaSoundMixer either start or updates the
* sample thru calls to JSThread.
*/
@Override
public void render(int dirtyFlags, View view, AuralParameters attribs) {
if (debugFlag)
debugPrint("JSSample.render ");
// if this is starting set gain, delay (for Pos), freq rate ...
// TODO: NOT SURE - leaving this in for now
float freqScaleFactor = attribs.frequencyScaleFactor;
if (attribs != null) {
if (freqScaleFactor <= 0.0f) {
// TODO: Pause Sample
}
else
rateRatio = currentRateRatio * freqScaleFactor;
}
else
rateRatio = currentRateRatio;
}
/**
* Clears/re-initialize fields associated with sample data for
* this sound,
* and frees any device specific data associated with this sample.
*/
@Override
public void clear() {
super.clear();
if (debugFlag)
debugPrintln("JSSample.clear() entered");
// TODO: unload sound data at device
// null out samples element that points to this?
// would this cause samples list size to shrink?
// if sample elements are never freed then does this mean
// a have a memory leak?
dataType = UNSUPPORTED_DATA_TYPE;
dataOffset = 0;
timeDeactivated = 0;
positionDeactivated = 0;
sampleLength = 0;
loopStartOffset = 0;
loopLength = 0;
attackLength = 0;
releaseLength = 0;
rateRatio = 1.0f;
channel = null;
if (debugFlag)
debugPrintln("JSSample.clear() exited");
}
// @return error true if error occurred
boolean load(MediaContainer soundData) {
/**
* Get the AudioInputStream first.
* MediaContiner passed to method assumed to be a clone of the
* application node with the query capability bits set on.
*/
String path = soundData.getURLString();
URL url = soundData.getURLObject();
InputStream inputStream = soundData.getInputStream();
boolean cacheFlag = soundData.getCacheEnable();
AudioInputStream ais = null;
DataLine dataLine = null;
// TODO: How do we determine if the file is a MIDI file???
// for now set dataType to BUFFERED_ or STREAMING_AUDIO_DATA
// used to test for ais instanceof AudioMidiInputStream ||
// ais instanceof AudioRmfInputStream )
// then set dataType = JSSample.BUFFERED_MIDI_DATA;
// QUESTION: can non-cached MIDI files ever be supported ?
/****************
// TODO: when we have a way to determine data type use code below
if (dataType==UNSUPPORTED_DATA_TYPE OR error_occurred)
clearSound(index);
if (debugFlag)
debugPrintln("JavaSoundMixer.prepareSound get dataType failed");
return true;
}
*****************/
// ...for now just check cacheFlag
if (cacheFlag)
dataType = BUFFERED_AUDIO_DATA;
else
dataType = STREAMING_AUDIO_DATA;
if ((url == null) && (inputStream == null) && (path == null)) {
if (debugFlag)
debugPrint("JavaSoundMixer.loadSound null data - return error");
return true;
}
// get ais
if (path != null) {
// generate url from string, and pass url to driver
if (debugFlag) {
debugPrint("JavaSoundMixer.loadSound with path = " + path);
}
try {
url = new URL(path);
}
catch (Exception e) {
// do not throw an exception while rendering
return true;
}
}
// get DataLine channel based on data type
if (dataType == BUFFERED_AUDIO_DATA) {
if (debugFlag)
debugPrintln("JSSample.load dataType = BUFFERED ");
channel = new JSClip();
if (debugFlag)
debugPrintln(" calls JSClip.initAudioInputStream");
if (url != null)
ais = channel.initAudioInputStream(url, cacheFlag);
else if (inputStream != null)
ais = channel.initAudioInputStream(inputStream, cacheFlag);
if (ais == null) {
if (debugFlag)
debugPrintln("JavaSoundMixer.prepareSound " +
"initAudioInputStream() failed");
return true;
}
if (debugFlag)
debugPrintln(" calls JSClip.initDataLine");
dataLine = channel.initDataLine(ais);
}
else if (dataType == STREAMING_AUDIO_DATA) {
if (debugFlag)
debugPrintln("JSSample.load dataType = STREAMING ");
channel = new JSStream();
if (debugFlag)
debugPrintln(" calls JSStream.initAudioInputStream");
if (url != null)
ais = channel.initAudioInputStream(url, cacheFlag);
else if (inputStream != null)
ais = channel.initAudioInputStream(inputStream, cacheFlag);
if (ais == null) {
if (debugFlag)
debugPrintln("JavaSoundMixer.prepareSound " +
"initAudioInputStream() failed");
return true;
}
if (debugFlag)
debugPrintln(" calls JSStream.initDataLine");
dataLine = channel.initDataLine(ais);
}
else {
if (debugFlag)
debugPrintln("JSSample.load doesn't support MIDI yet");
}
if (dataLine == null) {
if (debugFlag)
debugPrint("JSSample.load initDataLine failed ");
channel = null;
return true;
}
duration = channel.getDuration();
if (debugFlag)
debugPrint("JSSample.load channel duration = " + duration);
/*
* Since no error occurred while loading, save all the characteristics
* for the sound in the sample.
*/
setDirtyFlags(0xFFFF);
setSoundType(soundType);
setSoundData(soundData);
if (debugFlag)
debugPrintln("JSSample.load returned without error");
return false;
}
void reset() {
if (debugFlag)
debugPrint("JSSample.reset() exit");
rateRatio = 1.0f;
}
// TODO: NEED methods for any field accessed by both JSThread and
// JavaSoundMixer so that we can make these MT safe??
/*
* Process request for Filtering fields
*/
boolean getFilterFlag() {
return false;
}
float getFilterFreq() {
return -1.0f;
}
void setCurrentRateRatio(float ratio) {
currentRateRatio = ratio;
}
float getCurrentRateRatio() {
return currentRateRatio;
}
void setTargetRateRatio(float ratio) {
targetRateRatio = ratio;
}
float getTargetRateRatio() {
return targetRateRatio;
}
void setRampRateFlag(boolean flag) {
rampRateFlag = flag;
}
boolean getRampRateFlag() {
return rampRateFlag;
}
void setDataType(int type) {
dataType = type;
}
int getDataType() {
return dataType;
}
}