--- a/make/common/Release.gmk Thu Dec 25 20:43:44 2008 +0300
+++ b/make/common/Release.gmk Mon Jan 19 20:11:58 2009 +0300
@@ -912,14 +912,6 @@ initial-image-jdk:: initial-image-jdk-se
done
ifeq ($(PLATFORM), windows)
@#
- @# Audio soundbank - Bug# 4236400
- @# Windows only: adding audio files to JDK's jre/lib directory.
- @#
- ($(CD) $(LIBDIR) && $(TAR) cf - \
- `$(FIND) audio -depth -print`) | \
- ($(CD) $(JDK_IMAGE_DIR)/jre/lib && $(TAR) xf -)
- @#
- @#
@# lib/
@#
$(CP) $(LIBDIR)/$(LIB_PREFIX)jvm.$(LIB_SUFFIX) $(JDK_IMAGE_DIR)/lib
--- a/make/common/internal/BinaryPlugs.gmk Thu Dec 25 20:43:44 2008 +0300
+++ b/make/common/internal/BinaryPlugs.gmk Mon Jan 19 20:11:58 2009 +0300
@@ -29,9 +29,7 @@
# Names of native shared libraries
-PLUG_JSOUND_LIBRARY=$(LIB_PREFIX)jsoundhs.$(LIBRARY_SUFFIX)
-PLUG_LIBRARY_NAMES = \
- $(PLUG_JSOUND_LIBRARY)
+PLUG_LIBRARY_NAMES=
# Sub-directory where native shared libraries are located (e.g. jre/bin or...)
@@ -74,62 +72,10 @@ com/sun/jmx/snmp/daemon/SnmpTimerServer.
com/sun/jmx/snmp/daemon/SnmpTimerServer.class \
com/sun/jmx/snmp/daemon/WaitQ.class
-PLUG_SOUND_CLASS_NAMES = \
-com/sun/media/sound/AbstractPlayer.class \
-com/sun/media/sound/CircularBuffer.class \
-com/sun/media/sound/HeadspaceInstrument.class \
-com/sun/media/sound/HeadspaceMixer\$$1.class \
-com/sun/media/sound/HeadspaceMixer\$$MidiLine.class \
-com/sun/media/sound/HeadspaceMixer\$$MidiLineInfo.class \
-com/sun/media/sound/HeadspaceMixer\$$MixerInfo.class \
-com/sun/media/sound/HeadspaceMixer\$$MixerReverbControl\$$MixerReverbType.class \
-com/sun/media/sound/HeadspaceMixer\$$MixerReverbControl.class \
-com/sun/media/sound/HeadspaceMixer.class \
-com/sun/media/sound/HeadspaceMixerProvider.class \
-com/sun/media/sound/HeadspaceSample.class \
-com/sun/media/sound/HeadspaceSoundbank.class \
-com/sun/media/sound/HsbParser.class \
-com/sun/media/sound/MixerClip\$$1.class \
-com/sun/media/sound/MixerClip\$$MixerClipApplyReverbControl.class \
-com/sun/media/sound/MixerClip\$$MixerClipGainControl.class \
-com/sun/media/sound/MixerClip\$$MixerClipMuteControl.class \
-com/sun/media/sound/MixerClip\$$MixerClipPanControl.class \
-com/sun/media/sound/MixerClip\$$MixerClipSampleRateControl.class \
-com/sun/media/sound/MixerClip.class \
-com/sun/media/sound/MixerMidiChannel.class \
-com/sun/media/sound/MixerSequencer\$$1.class \
-com/sun/media/sound/MixerSequencer\$$ControllerVectorElement.class \
-com/sun/media/sound/MixerSequencer\$$MixerSequencerInfo.class \
-com/sun/media/sound/MixerSequencer\$$RecordingTrack.class \
-com/sun/media/sound/MixerSequencer.class \
-com/sun/media/sound/MixerSequencerProvider.class \
-com/sun/media/sound/MixerSourceLine\$$1.class \
-com/sun/media/sound/MixerSourceLine\$$MixerSourceLineApplyReverbControl.class \
-com/sun/media/sound/MixerSourceLine\$$MixerSourceLineGainControl.class \
-com/sun/media/sound/MixerSourceLine\$$MixerSourceLineMuteControl.class \
-com/sun/media/sound/MixerSourceLine\$$MixerSourceLinePanControl.class \
-com/sun/media/sound/MixerSourceLine\$$MixerSourceLineSampleRateControl.class \
-com/sun/media/sound/MixerSourceLine.class \
-com/sun/media/sound/MixerSynth\$$1.class \
-com/sun/media/sound/MixerSynth\$$MixerSynthInfo.class \
-com/sun/media/sound/MixerSynth\$$SynthReceiver.class \
-com/sun/media/sound/MixerSynth.class \
-com/sun/media/sound/MixerSynthProvider.class \
-com/sun/media/sound/MixerThread.class \
-com/sun/media/sound/RmfFileReader.class \
-com/sun/media/sound/SimpleInputDevice\$$1.class \
-com/sun/media/sound/SimpleInputDevice\$$InputDeviceDataLine.class \
-com/sun/media/sound/SimpleInputDevice\$$InputDevicePort.class \
-com/sun/media/sound/SimpleInputDevice\$$InputDevicePortInfo.class \
-com/sun/media/sound/SimpleInputDevice.class \
-com/sun/media/sound/SimpleInputDeviceProvider\$$1.class \
-com/sun/media/sound/SimpleInputDeviceProvider\$$InputDeviceInfo.class \
-com/sun/media/sound/SimpleInputDeviceProvider.class
-
# Class list temp files (used by both import and export of plugs)
PLUG_TEMPDIR=$(ABS_TEMPDIR)/plugs
-PLUG_CLASS_AREAS = jmf sound
+PLUG_CLASS_AREAS = jmf
PLUG_CLISTS = $(PLUG_CLASS_AREAS:%=$(PLUG_TEMPDIR)/%.clist)
# Create jargs file command
@@ -147,17 +93,10 @@ endef # plug-create-clist-jargs
@for i in $(PLUG_JMF_CLASS_NAMES) ; do \
$(ECHO) "$$i" >> $@; \
done
-$(PLUG_TEMPDIR)/sound.clist:
- @$(prep-target)
- @for i in $(PLUG_SOUND_CLASS_NAMES) ; do \
- $(ECHO) "$$i" >> $@ ; \
- done
$(PLUG_TEMPDIR)/all.clist: $(PLUG_CLISTS)
@$(prep-target)
$(CAT) $(PLUG_CLISTS) > $@
$(PLUG_TEMPDIR)/jmf.jargs: $(PLUG_TEMPDIR)/jmf.clist
- $(plug-create-jargs)
-$(PLUG_TEMPDIR)/sound.jargs: $(PLUG_TEMPDIR)/sound.clist
$(plug-create-jargs)
$(PLUG_TEMPDIR)/all.jargs: $(PLUG_TEMPDIR)/all.clist
$(plug-create-jargs)
@@ -193,25 +132,11 @@ endef # import-binary-plug-classes
import-binary-plug-jmf-classes: $(PLUG_IMPORT_JARFILE) $(PLUG_TEMPDIR)/jmf.clist
$(call import-binary-plug-classes,$(PLUG_TEMPDIR)/jmf.clist)
-import-binary-plug-sound-classes: $(PLUG_IMPORT_JARFILE) $(PLUG_TEMPDIR)/sound.clist
- $(call import-binary-plug-classes,$(PLUG_TEMPDIR)/sound.clist)
# Import all classes from the jar file
import-binary-plug-jar: \
- import-binary-plug-jmf-classes \
- import-binary-plug-sound-classes
-
-# Import native libraries
-
-$(LIB_LOCATION)/$(PLUG_JSOUND_LIBRARY): \
- $(PLUG_IMPORT_DIR)/$(PLUG_LOCATION_SUBDIR)/$(PLUG_JSOUND_LIBRARY)
- $(import-binary-plug-file)
-
-# Rules only used by lower level makefiles
-
-import-binary-plug-jsound-library: \
- $(LIB_LOCATION)/$(PLUG_JSOUND_LIBRARY)
+ import-binary-plug-jmf-classes
# Binary plug start/complete messages
@@ -241,9 +166,7 @@ import-binary-plugs: \
import-binary-plugs-libs \
import-binary-plugs \
import-binary-plug-jar \
- import-binary-plug-jmf-classes \
- import-binary-plug-sound-classes \
- import-binary-plug-jsound-library
+ import-binary-plug-jmf-classes
else # !OPENJDK
@@ -279,12 +202,6 @@ export-binary-plugs-license: $(PLUG_EXPO
$(BOOT_JAR_CMD) cf $@ @$(PLUG_TEMPDIR)/all.jargs $(BOOT_JAR_JFLAGS)
@$(java-vm-cleanup)
export-binary-plugs-jar: $(PLUG_EXPORT_JARFILE)
-
-# Export native libraries
-
-$(PLUG_EXPORT_DIR)/$(PLUG_LOCATION_SUBDIR)/$(PLUG_JSOUND_LIBRARY): \
- $(LIB_LOCATION)/$(PLUG_JSOUND_LIBRARY)
- $(export-binary-plug-file)
# Export binary plug start/complete messages
--- a/make/javax/sound/Makefile Thu Dec 25 20:43:44 2008 +0300
+++ b/make/javax/sound/Makefile Mon Jan 19 20:11:58 2009 +0300
@@ -52,18 +52,6 @@ include FILES_c.gmk
# add java files
AUTO_FILES_JAVA_DIRS = javax/sound com/sun/media/sound
-
-#
-# Specific to OpenJDK building
-#
-ifdef OPENJDK
-
-# copy closed .class files
-build: import-binary-plug-sound-classes
-
-include $(BUILDDIR)/common/internal/BinaryPlugs.gmk
-
-endif # OPENJDK
#
# Files that just need cp.
@@ -79,13 +67,11 @@ FILES_copy = \
$(SERVICEDIR)/javax.sound.sampled.spi.AudioFileReader \
$(SERVICEDIR)/javax.sound.sampled.spi.FormatConversionProvider \
$(SERVICEDIR)/javax.sound.sampled.spi.MixerProvider \
- $(LIBDIR)/audio/soundbank.gm \
$(LIBDIR)/sound.properties
FILES_mkdirs = \
$(CLASSBINDIR)/META-INF \
- $(CLASSBINDIR)/META-INF/services \
- $(LIBDIR)/audio
+ $(CLASSBINDIR)/META-INF/services
FILES_copydirs = \
$(CLASSBINDIR) \
@@ -94,11 +80,6 @@ FILES_copydirs = \
FILES_c += $(FILES_$(PLATFORM))
-
-#
-# add "closed" library
-#
-SUBDIRS += jsoundhs
#
# system dependent flags
--- a/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java Thu Dec 25 20:43:44 2008 +0300
+++ b/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java Mon Jan 19 20:11:58 2009 +0300
@@ -75,13 +75,6 @@ abstract class AbstractMidiDevice implem
/**
* This is the device handle returned from native code
*/
- /*
- * $$rratta Solaris 64 bit holds pointer must be long
- *
- * $$mp 2003-08-07:
- * 'id' is a really bad name. The variable should
- * be called nativePointer or something similar.
- */
protected long id = 0;
@@ -586,7 +579,6 @@ abstract class AbstractMidiDevice implem
private ArrayList<Transmitter> transmitters = new ArrayList<Transmitter>();
private MidiOutDevice.MidiOutReceiver midiOutReceiver;
- private MixerSynth.SynthReceiver mixerSynthReceiver;
// how many transmitters must be present for optimized
// handling
@@ -621,22 +613,14 @@ abstract class AbstractMidiDevice implem
if (midiOutReceiver == oldR) {
midiOutReceiver = null;
}
- if (mixerSynthReceiver == oldR) {
- mixerSynthReceiver = null;
- }
if (newR != null) {
if ((newR instanceof MidiOutDevice.MidiOutReceiver)
&& (midiOutReceiver == null)) {
midiOutReceiver = ((MidiOutDevice.MidiOutReceiver) newR);
}
- if ((newR instanceof MixerSynth.SynthReceiver)
- && (mixerSynthReceiver == null)) {
- mixerSynthReceiver = ((MixerSynth.SynthReceiver) newR);
- }
}
optimizedReceiverCount =
- ((midiOutReceiver!=null)?1:0)
- + ((mixerSynthReceiver!=null)?1:0);
+ ((midiOutReceiver!=null)?1:0);
}
// more potential for optimization here
}
@@ -670,10 +654,6 @@ abstract class AbstractMidiDevice implem
if (TRACE_TRANSMITTER) Printer.println("Sending packed message to MidiOutReceiver");
midiOutReceiver.sendPackedMidiMessage(packedMessage, timeStamp);
}
- if (mixerSynthReceiver != null) {
- if (TRACE_TRANSMITTER) Printer.println("Sending packed message to MixerSynthReceiver");
- mixerSynthReceiver.sendPackedMidiMessage(packedMessage, timeStamp);
- }
} else {
if (TRACE_TRANSMITTER) Printer.println("Sending packed message to "+size+" transmitter's receivers");
for (int i = 0; i < size; i++) {
@@ -682,9 +662,6 @@ abstract class AbstractMidiDevice implem
if (optimizedReceiverCount > 0) {
if (receiver instanceof MidiOutDevice.MidiOutReceiver) {
((MidiOutDevice.MidiOutReceiver) receiver).sendPackedMidiMessage(packedMessage, timeStamp);
- }
- else if (receiver instanceof MixerSynth.SynthReceiver) {
- ((MixerSynth.SynthReceiver) receiver).sendPackedMidiMessage(packedMessage, timeStamp);
} else {
receiver.send(new FastShortMessage(packedMessage), timeStamp);
}
@@ -739,10 +716,6 @@ abstract class AbstractMidiDevice implem
if (TRACE_TRANSMITTER) Printer.println("Sending MIDI message to MidiOutReceiver");
midiOutReceiver.send(message, timeStamp);
}
- if (mixerSynthReceiver != null) {
- if (TRACE_TRANSMITTER) Printer.println("Sending MIDI message to MixerSynthReceiver");
- mixerSynthReceiver.send(message, timeStamp);
- }
} else {
if (TRACE_TRANSMITTER) Printer.println("Sending MIDI message to "+size+" transmitter's receivers");
for (int i = 0; i < size; i++) {
--- a/src/share/classes/com/sun/media/sound/DirectAudioDevice.java Thu Dec 25 20:43:44 2008 +0300
+++ b/src/share/classes/com/sun/media/sound/DirectAudioDevice.java Mon Jan 19 20:11:58 2009 +0300
@@ -394,7 +394,12 @@ class DirectAudioDevice extends Abstract
private float leftGain, rightGain;
protected volatile boolean noService = false; // do not run the nService method
+ // Guards all native calls.
protected Object lockNative = new Object();
+ // Guards the lastOpened static variable in implOpen and implClose.
+ protected static Object lockLast = new Object();
+ // Keeps track of last opened line, see implOpen "trick".
+ protected static DirectDL lastOpened;
// CONSTRUCTOR
protected DirectDL(DataLine.Info info,
@@ -496,20 +501,50 @@ class DirectAudioDevice extends Abstract
// align buffer to full frames
bufferSize = ((int) bufferSize / format.getFrameSize()) * format.getFrameSize();
- id = nOpen(mixerIndex, deviceID, isSource,
- encoding,
- hardwareFormat.getSampleRate(),
- hardwareFormat.getSampleSizeInBits(),
- hardwareFormat.getFrameSize(),
- hardwareFormat.getChannels(),
- hardwareFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED),
- hardwareFormat.isBigEndian(),
- bufferSize);
-
- if (id == 0) {
- // TODO: nicer error messages...
- throw new LineUnavailableException("line with format "+format+" not supported.");
- }
+ synchronized(lockLast) {
+ id = nOpen(mixerIndex, deviceID, isSource,
+ encoding,
+ hardwareFormat.getSampleRate(),
+ hardwareFormat.getSampleSizeInBits(),
+ hardwareFormat.getFrameSize(),
+ hardwareFormat.getChannels(),
+ hardwareFormat.getEncoding().equals(
+ AudioFormat.Encoding.PCM_SIGNED),
+ hardwareFormat.isBigEndian(),
+ bufferSize);
+
+ if (id == 0) {
+ // Bah... Dirty trick. The most likely cause is an application
+ // already having a line open for this particular hardware
+ // format and forgetting about it. If so, silently close that
+ // implementation and try again. Unfortuantely we can only
+ // open one line per hardware format currently.
+ if (lastOpened != null
+ && hardwareFormat.matches(lastOpened.hardwareFormat)) {
+ lastOpened.implClose();
+ lastOpened = null;
+
+ id = nOpen(mixerIndex, deviceID, isSource,
+ encoding,
+ hardwareFormat.getSampleRate(),
+ hardwareFormat.getSampleSizeInBits(),
+ hardwareFormat.getFrameSize(),
+ hardwareFormat.getChannels(),
+ hardwareFormat.getEncoding().equals(
+ AudioFormat.Encoding.PCM_SIGNED),
+ hardwareFormat.isBigEndian(),
+ bufferSize);
+ }
+
+ if (id == 0) {
+ // TODO: nicer error messages...
+ throw new LineUnavailableException(
+ "line with format "+format+" not supported.");
+ }
+ }
+ lastOpened = this;
+ }
+
this.bufferSize = nGetBufferSize(id, isSource);
if (this.bufferSize < 1) {
// this is an error!
@@ -580,12 +615,12 @@ class DirectAudioDevice extends Abstract
}
synchronized (lockNative) {
nStop(id, isSource);
- }
-
- // need to set doIO to false before notifying the
- // read/write thread, that's why isStartedRunning()
- // cannot be used
- doIO = false;
+
+ // need to set doIO to false before notifying the
+ // read/write thread, that's why isStartedRunning()
+ // cannot be used
+ doIO = false;
+ }
// wake up any waiting threads
synchronized(lock) {
lock.notifyAll();
@@ -614,8 +649,12 @@ class DirectAudioDevice extends Abstract
doIO = false;
long oldID = id;
id = 0;
- synchronized (lockNative) {
- nClose(oldID, isSource);
+ synchronized (lockLast) {
+ synchronized (lockNative) {
+ nClose(oldID, isSource);
+ if (lastOpened == this)
+ lastOpened = null;
+ }
}
bytePosition = 0;
softwareConversionSize = 0;
@@ -630,7 +669,8 @@ class DirectAudioDevice extends Abstract
}
int a = 0;
synchronized (lockNative) {
- a = nAvailable(id, isSource);
+ if (doIO)
+ a = nAvailable(id, isSource);
}
return a;
}
@@ -644,9 +684,9 @@ class DirectAudioDevice extends Abstract
int counter = 0;
long startPos = getLongFramePosition();
boolean posChanged = false;
- while (!drained && doIO) {
+ while (!drained) {
synchronized (lockNative) {
- if ((id == 0) || !nIsStillDraining(id, isSource))
+ if ((id == 0) || (!doIO) || !nIsStillDraining(id, isSource))
break;
}
// check every now and then for a new position
@@ -686,7 +726,7 @@ class DirectAudioDevice extends Abstract
lock.notifyAll();
}
synchronized (lockNative) {
- if (id != 0) {
+ if (id != 0 && doIO) {
// then flush native buffers
nFlush(id, isSource);
}
@@ -697,9 +737,10 @@ class DirectAudioDevice extends Abstract
// replacement for getFramePosition (see AbstractDataLine)
public long getLongFramePosition() {
- long pos;
+ long pos = 0;
synchronized (lockNative) {
- pos = nGetBytePosition(id, isSource, bytePosition);
+ if (doIO)
+ pos = nGetBytePosition(id, isSource, bytePosition);
}
// hack because ALSA sometimes reports wrong framepos
if (pos < 0) {
@@ -745,11 +786,12 @@ class DirectAudioDevice extends Abstract
}
int written = 0;
while (!flushing) {
- int thisWritten;
+ int thisWritten = 0;
synchronized (lockNative) {
- thisWritten = nWrite(id, b, off, len,
- softwareConversionSize,
- leftGain, rightGain);
+ if (doIO)
+ thisWritten = nWrite(id, b, off, len,
+ softwareConversionSize,
+ leftGain, rightGain);
if (thisWritten < 0) {
// error in native layer
break;
@@ -972,9 +1014,10 @@ class DirectAudioDevice extends Abstract
}
int read = 0;
while (doIO && !flushing) {
- int thisRead;
+ int thisRead = 0;
synchronized (lockNative) {
- thisRead = nRead(id, b, off, len, softwareConversionSize);
+ if (doIO)
+ thisRead = nRead(id, b, off, len, softwareConversionSize);
if (thisRead < 0) {
// error in native layer
break;
@@ -1209,7 +1252,8 @@ class DirectAudioDevice extends Abstract
// set new native position (if necessary)
// this must come after the flush!
synchronized (lockNative) {
- nSetBytePosition(id, isSource, frames * frameSize);
+ if (doIO)
+ nSetBytePosition(id, isSource, frames * frameSize);
}
if (Printer.debug) Printer.debug(" DirectClip.setFramePosition: "
--- a/src/share/classes/com/sun/media/sound/Platform.java Thu Dec 25 20:43:44 2008 +0300
+++ b/src/share/classes/com/sun/media/sound/Platform.java Mon Jan 19 20:11:58 2009 +0300
@@ -42,8 +42,6 @@ class Platform {
// native library we need to load
private static final String libNameMain = "jsound";
- private static final String libNameMain2 = "jsoundhs";
-
private static final String libNameALSA = "jsoundalsa";
private static final String libNameDSound = "jsoundds";
@@ -158,9 +156,8 @@ class Platform {
if(Printer.trace)Printer.trace(">>Platform.loadLibraries");
try {
- // load the main libraries
+ // load the main library
JSSecurityManager.loadLibrary(libNameMain);
- JSSecurityManager.loadLibrary(libNameMain2);
// just for the heck of it...
loadedLibs |= LIB_MAIN;
} catch (SecurityException e) {
--- a/src/share/classes/com/sun/media/sound/RealTimeSequencer.java Thu Dec 25 20:43:44 2008 +0300
+++ b/src/share/classes/com/sun/media/sound/RealTimeSequencer.java Mon Jan 19 20:11:58 2009 +0300
@@ -54,10 +54,6 @@ class RealTimeSequencer extends Abstract
private final static boolean DEBUG_PUMP = false;
private final static boolean DEBUG_PUMP_ALL = false;
-
- /** if true, we bridge RMF files over to the old MixerSequencer */
- private final static boolean RMF = true;
-
/**
* Event Dispatcher thread. Should be using a shared event
* dispatcher instance with a factory in EventDispatcher
@@ -144,9 +140,6 @@ class RealTimeSequencer extends Abstract
*/
private ArrayList controllerEventListeners = new ArrayList();
-
- /** for RMF media we need the RMF sequencer */
- private MixerSequencer seqBridge = null;
/** automatic connection support */
private boolean autoConnect = false;
@@ -220,21 +213,6 @@ class RealTimeSequencer extends Abstract
playThread.setSequence(sequence);
}
}
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.close();
- seqBridge = null;
- }
- // if previous file was an RMF, but this file is not RMF,
- // then need to call implOpen again!
- if (isOpen() && sequence != null && playThread == null) {
- try {
- implOpen();
- } catch (MidiUnavailableException mue) {
- if (Printer.err) mue.printStackTrace();
- }
- }
- }
if (Printer.trace) Printer.trace("<< RealTimeSequencer: setSequence(" + sequence +") completed");
}
@@ -249,52 +227,6 @@ class RealTimeSequencer extends Abstract
return;
}
- // need to be able to detect RMF
- if (RMF) {
- MidiFileFormat fileFormat = MidiSystem.getMidiFileFormat(stream); // can throw IOException, InvalidMidiDataException
- int type = fileFormat.getType();
- int resolution = fileFormat.getResolution();
- if (Printer.debug) Printer.debug("Got file with type="+type+" and resolution="+resolution);
- if (resolution == MidiFileFormat.UNKNOWN_LENGTH) {
- // seems to be RMF
- if (seqBridge == null) {
- try {
- seqBridge = new MixerSequencer();
- if (isOpen()) {
- seqBridge.open();
- }
- } catch (MidiUnavailableException mue) {
- // uhum, strange situation. Need to cast to InvalidMidiDataException
- throw new InvalidMidiDataException(mue.getMessage());
- }
- }
- seqBridge.setSequence(stream);
- // propagate state
- seqBridge.setTempoFactor(getTempoFactor());
-
- // propagate listeners
- synchronized(metaEventListeners) {
- for (int i = 0 ; i < metaEventListeners.size(); i++) {
- seqBridge.addMetaEventListener((MetaEventListener) (metaEventListeners.get(i)));
- }
- }
- synchronized(controllerEventListeners) {
- for (int i = 0 ; i < controllerEventListeners.size(); i++) {
- ControllerListElement cve = (ControllerListElement) (controllerEventListeners.get(i));
- seqBridge.addControllerEventListener(cve.listener, cve.controllers);
- }
- }
- // disable the current sequence of RealTimeSequencer
- //setSequence((Sequence) null); -> will remove bridge again!
- this.sequence = null;
- return;
- }
- if (seqBridge != null) {
- seqBridge.close();
- seqBridge = null;
- }
- }
-
Sequence seq = MidiSystem.getSequence(stream); // can throw IOException, InvalidMidiDataException
setSequence(seq);
@@ -305,22 +237,11 @@ class RealTimeSequencer extends Abstract
public Sequence getSequence() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getSequence();
- }
- }
return sequence;
}
public synchronized void start() {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.start();
- return;
- }
- }
if (Printer.trace) Printer.trace(">> RealTimeSequencer: start()");
// sequencer not open: throw an exception
@@ -346,12 +267,6 @@ class RealTimeSequencer extends Abstract
public synchronized void stop() {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.stop();
- return;
- }
- }
if (Printer.trace) Printer.trace(">> RealTimeSequencer: stop()");
if (!isOpen()) {
@@ -373,23 +288,11 @@ class RealTimeSequencer extends Abstract
public boolean isRunning() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.isRunning();
- }
- }
return running;
}
public void startRecording() {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.startRecording();
- return;
- }
- }
-
if (!isOpen()) {
throw new IllegalStateException("Sequencer not open");
}
@@ -400,13 +303,6 @@ class RealTimeSequencer extends Abstract
public void stopRecording() {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.stopRecording();
- return;
- }
- }
-
if (!isOpen()) {
throw new IllegalStateException("Sequencer not open");
}
@@ -415,23 +311,11 @@ class RealTimeSequencer extends Abstract
public boolean isRecording() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.isRecording();
- }
- }
return recording;
}
public void recordEnable(Track track, int channel) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.recordEnable(track, channel);
- return;
- }
- }
-
if (!findTrack(track)) {
throw new IllegalArgumentException("Track does not exist in the current sequence");
}
@@ -449,13 +333,6 @@ class RealTimeSequencer extends Abstract
public void recordDisable(Track track) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.recordDisable(track);
- return;
- }
- }
-
synchronized(recordingTracks) {
RecordingTrack rc = RecordingTrack.get(recordingTracks, track);
if (rc != null) {
@@ -482,11 +359,6 @@ class RealTimeSequencer extends Abstract
public float getTempoInBPM() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getTempoInBPM();
- }
- }
if (Printer.trace) Printer.trace(">> RealTimeSequencer: getTempoInBPM() ");
return (float) MidiUtils.convertTempo(getTempoInMPQ());
@@ -494,12 +366,6 @@ class RealTimeSequencer extends Abstract
public void setTempoInBPM(float bpm) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.setTempoInBPM(bpm);
- return;
- }
- }
if (Printer.trace) Printer.trace(">> RealTimeSequencer: setTempoInBPM() ");
if (bpm <= 0) {
// should throw IllegalArgumentException
@@ -511,12 +377,6 @@ class RealTimeSequencer extends Abstract
public float getTempoInMPQ() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getTempoInMPQ();
- }
- }
-
if (Printer.trace) Printer.trace(">> RealTimeSequencer: getTempoInMPQ() ");
if (needCaching()) {
@@ -537,12 +397,6 @@ class RealTimeSequencer extends Abstract
public void setTempoInMPQ(float mpq) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.setTempoInMPQ(mpq);
- return;
- }
- }
if (mpq <= 0) {
// should throw IllegalArgumentException
mpq = 1.0f;
@@ -564,12 +418,6 @@ class RealTimeSequencer extends Abstract
public void setTempoFactor(float factor) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.setTempoFactor(factor);
- return;
- }
- }
if (factor <= 0) {
// should throw IllegalArgumentException
return;
@@ -588,11 +436,6 @@ class RealTimeSequencer extends Abstract
public float getTempoFactor() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getTempoFactor();
- }
- }
if (Printer.trace) Printer.trace(">> RealTimeSequencer: getTempoFactor() ");
if (needCaching()) {
@@ -606,11 +449,6 @@ class RealTimeSequencer extends Abstract
public long getTickLength() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getTickLength();
- }
- }
if (Printer.trace) Printer.trace(">> RealTimeSequencer: getTickLength() ");
if (sequence == null) {
@@ -622,11 +460,6 @@ class RealTimeSequencer extends Abstract
public synchronized long getTickPosition() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getTickPosition();
- }
- }
if (Printer.trace) Printer.trace(">> RealTimeSequencer: getTickPosition() ");
if (getDataPump() == null || sequence == null) {
@@ -638,12 +471,6 @@ class RealTimeSequencer extends Abstract
public synchronized void setTickPosition(long tick) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.setTickPosition(tick);
- return;
- }
- }
if (tick < 0) {
// should throw IllegalArgumentException
return;
@@ -667,12 +494,6 @@ class RealTimeSequencer extends Abstract
public long getMicrosecondLength() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getMicrosecondLength();
- }
- }
-
if (Printer.trace) Printer.trace(">> RealTimeSequencer: getMicrosecondLength() ");
if (sequence == null) {
@@ -684,12 +505,6 @@ class RealTimeSequencer extends Abstract
public long getMicrosecondPosition() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getMicrosecondPosition();
- }
- }
-
if (Printer.trace) Printer.trace(">> RealTimeSequencer: getMicrosecondPosition() ");
if (getDataPump() == null || sequence == null) {
@@ -702,13 +517,6 @@ class RealTimeSequencer extends Abstract
public void setMicrosecondPosition(long microseconds) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.setMicrosecondPosition(microseconds);
- return;
- }
- }
-
if (microseconds < 0) {
// should throw IllegalArgumentException
return;
@@ -734,33 +542,16 @@ class RealTimeSequencer extends Abstract
public void setMasterSyncMode(Sequencer.SyncMode sync) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.setMasterSyncMode(sync);
- return;
- }
- }
// not supported
}
public Sequencer.SyncMode getMasterSyncMode() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getMasterSyncMode();
- }
- }
return masterSyncMode;
}
public Sequencer.SyncMode[] getMasterSyncModes() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getMasterSyncModes();
- }
- }
-
Sequencer.SyncMode[] returnedModes = new Sequencer.SyncMode[masterSyncModes.length];
System.arraycopy(masterSyncModes, 0, returnedModes, 0, masterSyncModes.length);
return returnedModes;
@@ -768,33 +559,16 @@ class RealTimeSequencer extends Abstract
public void setSlaveSyncMode(Sequencer.SyncMode sync) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.setSlaveSyncMode(sync);
- return;
- }
- }
// not supported
}
public Sequencer.SyncMode getSlaveSyncMode() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getSlaveSyncMode();
- }
- }
return slaveSyncMode;
}
public Sequencer.SyncMode[] getSlaveSyncModes() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getSlaveSyncModes();
- }
- }
-
Sequencer.SyncMode[] returnedModes = new Sequencer.SyncMode[slaveSyncModes.length];
System.arraycopy(slaveSyncModes, 0, returnedModes, 0, slaveSyncModes.length);
return returnedModes;
@@ -812,12 +586,6 @@ class RealTimeSequencer extends Abstract
public synchronized void setTrackMute(int track, boolean mute) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.setTrackMute(track, mute);
- return;
- }
- }
int trackCount = getTrackCount();
if (track < 0 || track >= getTrackCount()) return;
trackMuted = ensureBoolArraySize(trackMuted, trackCount);
@@ -829,11 +597,6 @@ class RealTimeSequencer extends Abstract
public synchronized boolean getTrackMute(int track) {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getTrackMute(track);
- }
- }
if (track < 0 || track >= getTrackCount()) return false;
if (trackMuted == null || trackMuted.length <= track) return false;
return trackMuted[track];
@@ -841,12 +604,6 @@ class RealTimeSequencer extends Abstract
public synchronized void setTrackSolo(int track, boolean solo) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.setTrackSolo(track, solo);
- return;
- }
- }
int trackCount = getTrackCount();
if (track < 0 || track >= getTrackCount()) return;
trackSolo = ensureBoolArraySize(trackSolo, trackCount);
@@ -858,11 +615,6 @@ class RealTimeSequencer extends Abstract
public synchronized boolean getTrackSolo(int track) {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getTrackSolo(track);
- }
- }
if (track < 0 || track >= getTrackCount()) return false;
if (trackSolo == null || trackSolo.length <= track) return false;
return trackSolo[track];
@@ -870,12 +622,6 @@ class RealTimeSequencer extends Abstract
public boolean addMetaEventListener(MetaEventListener listener) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.addMetaEventListener(listener);
- // do not return here!
- }
- }
synchronized(metaEventListeners) {
if (! metaEventListeners.contains(listener)) {
@@ -887,12 +633,6 @@ class RealTimeSequencer extends Abstract
public void removeMetaEventListener(MetaEventListener listener) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.removeMetaEventListener(listener);
- // do not return here!
- }
- }
synchronized(metaEventListeners) {
int index = metaEventListeners.indexOf(listener);
if (index >= 0) {
@@ -903,13 +643,6 @@ class RealTimeSequencer extends Abstract
public int[] addControllerEventListener(ControllerEventListener listener, int[] controllers) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.addControllerEventListener(listener, controllers);
- // do not return here!
- }
- }
-
synchronized(controllerEventListeners) {
// first find the listener. if we have one, add the controllers
@@ -938,12 +671,6 @@ class RealTimeSequencer extends Abstract
public int[] removeControllerEventListener(ControllerEventListener listener, int[] controllers) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.removeControllerEventListener(listener, controllers);
- // do not return here!
- }
- }
synchronized(controllerEventListeners) {
ControllerListElement cve = null;
boolean flag = false;
@@ -973,12 +700,6 @@ class RealTimeSequencer extends Abstract
////////////////// LOOPING (added in 1.5) ///////////////////////
public void setLoopStartPoint(long tick) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.setLoopStartPoint(tick);
- return;
- }
- }
if ((tick > getTickLength())
|| ((loopEnd != -1) && (tick > loopEnd))
|| (tick < 0)) {
@@ -988,21 +709,10 @@ class RealTimeSequencer extends Abstract
}
public long getLoopStartPoint() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getLoopStartPoint();
- }
- }
return loopStart;
}
public void setLoopEndPoint(long tick) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.setLoopEndPoint(tick);
- return;
- }
- }
if ((tick > getTickLength())
|| ((loopStart > tick) && (tick != -1))
|| (tick < -1)) {
@@ -1012,21 +722,10 @@ class RealTimeSequencer extends Abstract
}
public long getLoopEndPoint() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getLoopEndPoint();
- }
- }
return loopEnd;
}
public void setLoopCount(int count) {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.setLoopCount(count);
- return;
- }
- }
if (count != LOOP_CONTINUOUSLY
&& count < 0) {
throw new IllegalArgumentException("illegal value for loop count: "+count);
@@ -1038,11 +737,6 @@ class RealTimeSequencer extends Abstract
}
public int getLoopCount() {
- if (RMF) {
- if (seqBridge != null) {
- return seqBridge.getLoopCount();
- }
- }
return loopCount;
}
@@ -1053,13 +747,6 @@ class RealTimeSequencer extends Abstract
*/
protected void implOpen() throws MidiUnavailableException {
if (Printer.trace) Printer.trace(">> RealTimeSequencer: implOpen()");
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.open();
- if (Printer.trace) Printer.trace("<< RealTimeSequencer: -> called seqBridge.open");
- return;
- }
- }
//openInternalSynth();
@@ -1095,12 +782,6 @@ class RealTimeSequencer extends Abstract
synth.open();
if (synth instanceof ReferenceCountingDevice) {
rec = ((ReferenceCountingDevice) synth).getReceiverReferenceCounting();
- if (synth.getClass().toString().contains("com.sun.media.sound.MixerSynth")
- && (synth.getDefaultSoundbank() == null)) {
- // don't use this receiver if no soundbank available
- rec = null;
- synth.close();
- }
} else {
rec = synth.getReceiver();
}
@@ -1147,12 +828,6 @@ class RealTimeSequencer extends Abstract
protected synchronized void implClose() {
- if (RMF) {
- if (seqBridge != null) {
- seqBridge.close();
- // don't return here!
- }
- }
if (Printer.trace) Printer.trace(">> RealTimeSequencer: implClose() ");
if (playThread == null) {
@@ -1302,12 +977,6 @@ class RealTimeSequencer extends Abstract
// OVERRIDES OF ABSTRACT MIDI DEVICE METHODS
protected boolean hasReceivers() {
- if (RMF) {
- if (seqBridge != null) {
- //RMF does not allow recording
- return false;
- }
- }
return true;
}
@@ -1318,12 +987,6 @@ class RealTimeSequencer extends Abstract
protected boolean hasTransmitters() {
- if (RMF) {
- if (seqBridge != null) {
- //RMF does never allow setting own receivers
- return false;
- }
- }
return true;
}
--- a/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider Thu Dec 25 20:43:44 2008 +0300
+++ b/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider Mon Jan 19 20:11:58 2009 +0300
@@ -1,5 +1,5 @@
# Providers for midi devices
-com.sun.media.sound.MixerSynthProvider
com.sun.media.sound.RealTimeSequencerProvider
com.sun.media.sound.MidiOutDeviceProvider
com.sun.media.sound.MidiInDeviceProvider
+com.sun.media.sound.SoftProvider
--- a/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiFileReader Thu Dec 25 20:43:44 2008 +0300
+++ b/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiFileReader Mon Jan 19 20:11:58 2009 +0300
@@ -1,3 +1,2 @@
# Providers for midi sequences
com.sun.media.sound.StandardMidiFileReader
-com.sun.media.sound.RmfFileReader
--- a/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.SoundbankReader Thu Dec 25 20:43:44 2008 +0300
+++ b/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.SoundbankReader Mon Jan 19 20:11:58 2009 +0300
@@ -1,2 +1,5 @@
# Providers for Soundbanks
-com.sun.media.sound.HsbParser
+com.sun.media.sound.SF2SoundbankReader
+com.sun.media.sound.DLSSoundbankReader
+com.sun.media.sound.AudioFileSoundbankReader
+com.sun.media.sound.JARSoundbankReader
--- a/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.AudioFileReader Thu Dec 25 20:43:44 2008 +0300
+++ b/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.AudioFileReader Mon Jan 19 20:11:58 2009 +0300
@@ -2,3 +2,5 @@ com.sun.media.sound.AuFileReader
com.sun.media.sound.AuFileReader
com.sun.media.sound.AiffFileReader
com.sun.media.sound.WaveFileReader
+com.sun.media.sound.WaveFloatFileReader
+com.sun.media.sound.SoftMidiAudioFileReader
--- a/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.FormatConversionProvider Thu Dec 25 20:43:44 2008 +0300
+++ b/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.FormatConversionProvider Mon Jan 19 20:11:58 2009 +0300
@@ -2,3 +2,4 @@ com.sun.media.sound.UlawCodec
com.sun.media.sound.UlawCodec
com.sun.media.sound.AlawCodec
com.sun.media.sound.PCMtoPCMCodec
+com.sun.media.sound.AudioFloatFormatConverter
--- a/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.MixerProvider Thu Dec 25 20:43:44 2008 +0300
+++ b/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.MixerProvider Mon Jan 19 20:11:58 2009 +0300
@@ -1,5 +1,3 @@
# last mixer is default mixer
com.sun.media.sound.PortMixerProvider
-com.sun.media.sound.SimpleInputDeviceProvider
-com.sun.media.sound.HeadspaceMixerProvider
com.sun.media.sound.DirectAudioDeviceProvider
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/media/sound/AudioFileSoundbankReader.java Mon Jan 19 20:11:58 2009 +0300
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.media.sound;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.spi.SoundbankReader;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.UnsupportedAudioFileException;
+
+/**
+ * Soundbank reader that uses audio files as soundbanks.
+ *
+ * @author Karl Helgason
+ */
+public class AudioFileSoundbankReader extends SoundbankReader {
+
+ public Soundbank getSoundbank(URL url)
+ throws InvalidMidiDataException, IOException {
+ try {
+ AudioInputStream ais = AudioSystem.getAudioInputStream(url);
+ Soundbank sbk = getSoundbank(ais);
+ ais.close();
+ return sbk;
+ } catch (UnsupportedAudioFileException e) {
+ return null;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ public Soundbank getSoundbank(InputStream stream)
+ throws InvalidMidiDataException, IOException {
+ stream.mark(512);
+ try {
+ AudioInputStream ais = AudioSystem.getAudioInputStream(stream);
+ Soundbank sbk = getSoundbank(ais);
+ if (sbk != null)
+ return sbk;
+ } catch (UnsupportedAudioFileException e) {
+ } catch (IOException e) {
+ }
+ stream.reset();
+ return null;
+ }
+
+ public Soundbank getSoundbank(AudioInputStream ais)
+ throws InvalidMidiDataException, IOException {
+ try {
+ byte[] buffer;
+ if (ais.getFrameLength() == -1) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buff = new byte[1024
+ - (1024 % ais.getFormat().getFrameSize())];
+ int ret;
+ while ((ret = ais.read(buff)) != -1) {
+ baos.write(buff, 0, ret);
+ }
+ ais.close();
+ buffer = baos.toByteArray();
+ } else {
+ buffer = new byte[(int) (ais.getFrameLength()
+ * ais.getFormat().getFrameSize())];
+ new DataInputStream(ais).readFully(buffer);
+ }
+ ModelByteBufferWavetable osc = new ModelByteBufferWavetable(
+ new ModelByteBuffer(buffer), ais.getFormat(), -4800);
+ ModelPerformer performer = new ModelPerformer();
+ performer.getOscillators().add(osc);
+
+ SimpleSoundbank sbk = new SimpleSoundbank();
+ SimpleInstrument ins = new SimpleInstrument();
+ ins.add(performer);
+ sbk.addInstrument(ins);
+ return sbk;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public Soundbank getSoundbank(File file)
+ throws InvalidMidiDataException, IOException {
+ try {
+ AudioInputStream ais = AudioSystem.getAudioInputStream(file);
+ ais.close();
+ ModelByteBufferWavetable osc = new ModelByteBufferWavetable(
+ new ModelByteBuffer(file, 0, file.length()), -4800);
+ ModelPerformer performer = new ModelPerformer();
+ performer.getOscillators().add(osc);
+ SimpleSoundbank sbk = new SimpleSoundbank();
+ SimpleInstrument ins = new SimpleInstrument();
+ ins.add(performer);
+ sbk.addInstrument(ins);
+ return sbk;
+ } catch (UnsupportedAudioFileException e1) {
+ return null;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/media/sound/AudioFloatConverter.java Mon Jan 19 20:11:58 2009 +0300
@@ -0,0 +1,1058 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.media.sound;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
+
+/**
+ * This class is used to convert between 8,16,24,32,32+ bit signed/unsigned
+ * big/litle endian fixed/floating point byte buffers and float buffers.
+ *
+ * @author Karl Helgason
+ */
+public abstract class AudioFloatConverter {
+
+ public static final Encoding PCM_FLOAT = new Encoding("PCM_FLOAT");
+
+ /***************************************************************************
+ *
+ * LSB Filter, used filter least significant byte in samples arrays.
+ *
+ * Is used filter out data in lsb byte when SampleSizeInBits is not
+ * dividable by 8.
+ *
+ **************************************************************************/
+
+ private static class AudioFloatLSBFilter extends AudioFloatConverter {
+
+ private AudioFloatConverter converter;
+
+ final private int offset;
+
+ final private int stepsize;
+
+ final private byte mask;
+
+ private byte[] mask_buffer;
+
+ public AudioFloatLSBFilter(AudioFloatConverter converter,
+ AudioFormat format) {
+ int bits = format.getSampleSizeInBits();
+ boolean bigEndian = format.isBigEndian();
+ this.converter = converter;
+ stepsize = (bits + 7) / 8;
+ offset = bigEndian ? (stepsize - 1) : 0;
+ int lsb_bits = bits % 8;
+ if (lsb_bits == 0)
+ mask = (byte) 0x00;
+ else if (lsb_bits == 1)
+ mask = (byte) 0x80;
+ else if (lsb_bits == 2)
+ mask = (byte) 0xC0;
+ else if (lsb_bits == 3)
+ mask = (byte) 0xE0;
+ else if (lsb_bits == 4)
+ mask = (byte) 0xF0;
+ else if (lsb_bits == 5)
+ mask = (byte) 0xF8;
+ else if (lsb_bits == 6)
+ mask = (byte) 0xFC;
+ else if (lsb_bits == 7)
+ mask = (byte) 0xFE;
+ else
+ mask = (byte) 0xFF;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ byte[] ret = converter.toByteArray(in_buff, in_offset, in_len,
+ out_buff, out_offset);
+
+ int out_offset_end = in_len * stepsize;
+ for (int i = out_offset + offset; i < out_offset_end; i += stepsize) {
+ out_buff[i] = (byte) (out_buff[i] & mask);
+ }
+
+ return ret;
+ }
+
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ if (mask_buffer == null || mask_buffer.length < in_buff.length)
+ mask_buffer = new byte[in_buff.length];
+ System.arraycopy(in_buff, 0, mask_buffer, 0, in_buff.length);
+ int in_offset_end = out_len * stepsize;
+ for (int i = in_offset + offset; i < in_offset_end; i += stepsize) {
+ mask_buffer[i] = (byte) (mask_buffer[i] & mask);
+ }
+ float[] ret = converter.toFloatArray(mask_buffer, in_offset,
+ out_buff, out_offset, out_len);
+ return ret;
+ }
+
+ }
+
+ /***************************************************************************
+ *
+ * 64 bit float, little/big-endian
+ *
+ **************************************************************************/
+
+ // PCM 64 bit float, little-endian
+ private static class AudioFloatConversion64L extends AudioFloatConverter {
+ ByteBuffer bytebuffer = null;
+
+ DoubleBuffer floatbuffer = null;
+
+ double[] double_buff = null;
+
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int in_len = out_len * 8;
+ if (bytebuffer == null || bytebuffer.capacity() < in_len) {
+ bytebuffer = ByteBuffer.allocate(in_len).order(
+ ByteOrder.LITTLE_ENDIAN);
+ floatbuffer = bytebuffer.asDoubleBuffer();
+ }
+ bytebuffer.position(0);
+ floatbuffer.position(0);
+ bytebuffer.put(in_buff, in_offset, in_len);
+ if (double_buff == null
+ || double_buff.length < out_len + out_offset)
+ double_buff = new double[out_len + out_offset];
+ floatbuffer.get(double_buff, out_offset, out_len);
+ int out_offset_end = out_offset + out_len;
+ for (int i = out_offset; i < out_offset_end; i++) {
+ out_buff[i] = (float) double_buff[i];
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int out_len = in_len * 8;
+ if (bytebuffer == null || bytebuffer.capacity() < out_len) {
+ bytebuffer = ByteBuffer.allocate(out_len).order(
+ ByteOrder.LITTLE_ENDIAN);
+ floatbuffer = bytebuffer.asDoubleBuffer();
+ }
+ floatbuffer.position(0);
+ bytebuffer.position(0);
+ if (double_buff == null || double_buff.length < in_offset + in_len)
+ double_buff = new double[in_offset + in_len];
+ int in_offset_end = in_offset + in_len;
+ for (int i = in_offset; i < in_offset_end; i++) {
+ double_buff[i] = in_buff[i];
+ }
+ floatbuffer.put(double_buff, in_offset, in_len);
+ bytebuffer.get(out_buff, out_offset, out_len);
+ return out_buff;
+ }
+ }
+
+ // PCM 64 bit float, big-endian
+ private static class AudioFloatConversion64B extends AudioFloatConverter {
+ ByteBuffer bytebuffer = null;
+
+ DoubleBuffer floatbuffer = null;
+
+ double[] double_buff = null;
+
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int in_len = out_len * 8;
+ if (bytebuffer == null || bytebuffer.capacity() < in_len) {
+ bytebuffer = ByteBuffer.allocate(in_len).order(
+ ByteOrder.BIG_ENDIAN);
+ floatbuffer = bytebuffer.asDoubleBuffer();
+ }
+ bytebuffer.position(0);
+ floatbuffer.position(0);
+ bytebuffer.put(in_buff, in_offset, in_len);
+ if (double_buff == null
+ || double_buff.length < out_len + out_offset)
+ double_buff = new double[out_len + out_offset];
+ floatbuffer.get(double_buff, out_offset, out_len);
+ int out_offset_end = out_offset + out_len;
+ for (int i = out_offset; i < out_offset_end; i++) {
+ out_buff[i] = (float) double_buff[i];
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int out_len = in_len * 8;
+ if (bytebuffer == null || bytebuffer.capacity() < out_len) {
+ bytebuffer = ByteBuffer.allocate(out_len).order(
+ ByteOrder.BIG_ENDIAN);
+ floatbuffer = bytebuffer.asDoubleBuffer();
+ }
+ floatbuffer.position(0);
+ bytebuffer.position(0);
+ if (double_buff == null || double_buff.length < in_offset + in_len)
+ double_buff = new double[in_offset + in_len];
+ int in_offset_end = in_offset + in_len;
+ for (int i = in_offset; i < in_offset_end; i++) {
+ double_buff[i] = in_buff[i];
+ }
+ floatbuffer.put(double_buff, in_offset, in_len);
+ bytebuffer.get(out_buff, out_offset, out_len);
+ return out_buff;
+ }
+ }
+
+ /***************************************************************************
+ *
+ * 32 bit float, little/big-endian
+ *
+ **************************************************************************/
+
+ // PCM 32 bit float, little-endian
+ private static class AudioFloatConversion32L extends AudioFloatConverter {
+ ByteBuffer bytebuffer = null;
+
+ FloatBuffer floatbuffer = null;
+
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int in_len = out_len * 4;
+ if (bytebuffer == null || bytebuffer.capacity() < in_len) {
+ bytebuffer = ByteBuffer.allocate(in_len).order(
+ ByteOrder.LITTLE_ENDIAN);
+ floatbuffer = bytebuffer.asFloatBuffer();
+ }
+ bytebuffer.position(0);
+ floatbuffer.position(0);
+ bytebuffer.put(in_buff, in_offset, in_len);
+ floatbuffer.get(out_buff, out_offset, out_len);
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int out_len = in_len * 4;
+ if (bytebuffer == null || bytebuffer.capacity() < out_len) {
+ bytebuffer = ByteBuffer.allocate(out_len).order(
+ ByteOrder.LITTLE_ENDIAN);
+ floatbuffer = bytebuffer.asFloatBuffer();
+ }
+ floatbuffer.position(0);
+ bytebuffer.position(0);
+ floatbuffer.put(in_buff, in_offset, in_len);
+ bytebuffer.get(out_buff, out_offset, out_len);
+ return out_buff;
+ }
+ }
+
+ // PCM 32 bit float, big-endian
+ private static class AudioFloatConversion32B extends AudioFloatConverter {
+ ByteBuffer bytebuffer = null;
+
+ FloatBuffer floatbuffer = null;
+
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int in_len = out_len * 4;
+ if (bytebuffer == null || bytebuffer.capacity() < in_len) {
+ bytebuffer = ByteBuffer.allocate(in_len).order(
+ ByteOrder.BIG_ENDIAN);
+ floatbuffer = bytebuffer.asFloatBuffer();
+ }
+ bytebuffer.position(0);
+ floatbuffer.position(0);
+ bytebuffer.put(in_buff, in_offset, in_len);
+ floatbuffer.get(out_buff, out_offset, out_len);
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int out_len = in_len * 4;
+ if (bytebuffer == null || bytebuffer.capacity() < out_len) {
+ bytebuffer = ByteBuffer.allocate(out_len).order(
+ ByteOrder.BIG_ENDIAN);
+ floatbuffer = bytebuffer.asFloatBuffer();
+ }
+ floatbuffer.position(0);
+ bytebuffer.position(0);
+ floatbuffer.put(in_buff, in_offset, in_len);
+ bytebuffer.get(out_buff, out_offset, out_len);
+ return out_buff;
+ }
+ }
+
+ /***************************************************************************
+ *
+ * 8 bit signed/unsigned
+ *
+ **************************************************************************/
+
+ // PCM 8 bit, signed
+ private static class AudioFloatConversion8S extends AudioFloatConverter {
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++)
+ out_buff[ox++] = in_buff[ix++] * (1.0f / 127.0f);
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++)
+ out_buff[ox++] = (byte) (in_buff[ix++] * 127.0f);
+ return out_buff;
+ }
+ }
+
+ // PCM 8 bit, unsigned
+ private static class AudioFloatConversion8U extends AudioFloatConverter {
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++)
+ out_buff[ox++] = ((in_buff[ix++] & 0xFF) - 127)
+ * (1.0f / 127.0f);
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++)
+ out_buff[ox++] = (byte) (127 + in_buff[ix++] * 127.0f);
+ return out_buff;
+ }
+ }
+
+ /***************************************************************************
+ *
+ * 16 bit signed/unsigned, little/big-endian
+ *
+ **************************************************************************/
+
+ // PCM 16 bit, signed, little-endian
+ private static class AudioFloatConversion16SL extends AudioFloatConverter {
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int len = out_offset + out_len;
+ for (int ox = out_offset; ox < len; ox++) {
+ out_buff[ox] = ((short) ((in_buff[ix++] & 0xFF) |
+ (in_buff[ix++] << 8))) * (1.0f / 32767.0f);
+ }
+
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ox = out_offset;
+ int len = in_offset + in_len;
+ for (int ix = in_offset; ix < len; ix++) {
+ int x = (int) (in_buff[ix] * 32767.0);
+ out_buff[ox++] = (byte) x;
+ out_buff[ox++] = (byte) (x >>> 8);
+ }
+ return out_buff;
+ }
+ }
+
+ // PCM 16 bit, signed, big-endian
+ private static class AudioFloatConversion16SB extends AudioFloatConverter {
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ out_buff[ox++] = ((short) ((in_buff[ix++] << 8) |
+ (in_buff[ix++] & 0xFF))) * (1.0f / 32767.0f);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = (int) (in_buff[ix++] * 32767.0);
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) x;
+ }
+ return out_buff;
+ }
+ }
+
+ // PCM 16 bit, unsigned, little-endian
+ private static class AudioFloatConversion16UL extends AudioFloatConverter {
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8);
+ out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = 32767 + (int) (in_buff[ix++] * 32767.0);
+ out_buff[ox++] = (byte) x;
+ out_buff[ox++] = (byte) (x >>> 8);
+ }
+ return out_buff;
+ }
+ }
+
+ // PCM 16 bit, unsigned, big-endian
+ private static class AudioFloatConversion16UB extends AudioFloatConverter {
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ int x = ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
+ out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = 32767 + (int) (in_buff[ix++] * 32767.0);
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) x;
+ }
+ return out_buff;
+ }
+ }
+
+ /***************************************************************************
+ *
+ * 24 bit signed/unsigned, little/big-endian
+ *
+ **************************************************************************/
+
+ // PCM 24 bit, signed, little-endian
+ private static class AudioFloatConversion24SL extends AudioFloatConverter {
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
+ | ((in_buff[ix++] & 0xFF) << 16);
+ if (x > 0x7FFFFF)
+ x -= 0x1000000;
+ out_buff[ox++] = x * (1.0f / (float)0x7FFFFF);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = (int) (in_buff[ix++] * (float)0x7FFFFF);
+ if (x < 0)
+ x += 0x1000000;
+ out_buff[ox++] = (byte) x;
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) (x >>> 16);
+ }
+ return out_buff;
+ }
+ }
+
+ // PCM 24 bit, signed, big-endian
+ private static class AudioFloatConversion24SB extends AudioFloatConverter {
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ int x = ((in_buff[ix++] & 0xFF) << 16)
+ | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
+ if (x > 0x7FFFFF)
+ x -= 0x1000000;
+ out_buff[ox++] = x * (1.0f / (float)0x7FFFFF);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = (int) (in_buff[ix++] * (float)0x7FFFFF);
+ if (x < 0)
+ x += 0x1000000;
+ out_buff[ox++] = (byte) (x >>> 16);
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) x;
+ }
+ return out_buff;
+ }
+ }
+
+ // PCM 24 bit, unsigned, little-endian
+ private static class AudioFloatConversion24UL extends AudioFloatConverter {
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
+ | ((in_buff[ix++] & 0xFF) << 16);
+ x -= 0x7FFFFF;
+ out_buff[ox++] = x * (1.0f / (float)0x7FFFFF);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = (int) (in_buff[ix++] * (float)0x7FFFFF);
+ x += 0x7FFFFF;
+ out_buff[ox++] = (byte) x;
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) (x >>> 16);
+ }
+ return out_buff;
+ }
+ }
+
+ // PCM 24 bit, unsigned, big-endian
+ private static class AudioFloatConversion24UB extends AudioFloatConverter {
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ int x = ((in_buff[ix++] & 0xFF) << 16)
+ | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
+ x -= 0x7FFFFF;
+ out_buff[ox++] = x * (1.0f / (float)0x7FFFFF);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = (int) (in_buff[ix++] * (float)0x7FFFFF);
+ x += 0x7FFFFF;
+ out_buff[ox++] = (byte) (x >>> 16);
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) x;
+ }
+ return out_buff;
+ }
+ }
+
+ /***************************************************************************
+ *
+ * 32 bit signed/unsigned, little/big-endian
+ *
+ **************************************************************************/
+
+ // PCM 32 bit, signed, little-endian
+ private static class AudioFloatConversion32SL extends AudioFloatConverter {
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) |
+ ((in_buff[ix++] & 0xFF) << 16) |
+ ((in_buff[ix++] & 0xFF) << 24);
+ out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
+ out_buff[ox++] = (byte) x;
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) (x >>> 16);
+ out_buff[ox++] = (byte) (x >>> 24);
+ }
+ return out_buff;
+ }
+ }
+
+ // PCM 32 bit, signed, big-endian
+ private static class AudioFloatConversion32SB extends AudioFloatConverter {
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ int x = ((in_buff[ix++] & 0xFF) << 24) |
+ ((in_buff[ix++] & 0xFF) << 16) |
+ ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
+ out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
+ out_buff[ox++] = (byte) (x >>> 24);
+ out_buff[ox++] = (byte) (x >>> 16);
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) x;
+ }
+ return out_buff;
+ }
+ }
+
+ // PCM 32 bit, unsigned, little-endian
+ private static class AudioFloatConversion32UL extends AudioFloatConverter {
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) |
+ ((in_buff[ix++] & 0xFF) << 16) |
+ ((in_buff[ix++] & 0xFF) << 24);
+ x -= 0x7FFFFFFF;
+ out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
+ x += 0x7FFFFFFF;
+ out_buff[ox++] = (byte) x;
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) (x >>> 16);
+ out_buff[ox++] = (byte) (x >>> 24);
+ }
+ return out_buff;
+ }
+ }
+
+ // PCM 32 bit, unsigned, big-endian
+ private static class AudioFloatConversion32UB extends AudioFloatConverter {
+
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ int x = ((in_buff[ix++] & 0xFF) << 24) |
+ ((in_buff[ix++] & 0xFF) << 16) |
+ ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
+ x -= 0x7FFFFFFF;
+ out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
+ x += 0x7FFFFFFF;
+ out_buff[ox++] = (byte) (x >>> 24);
+ out_buff[ox++] = (byte) (x >>> 16);
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) x;
+ }
+ return out_buff;
+ }
+ }
+
+ /***************************************************************************
+ *
+ * 32+ bit signed/unsigned, little/big-endian
+ *
+ **************************************************************************/
+
+ // PCM 32+ bit, signed, little-endian
+ private static class AudioFloatConversion32xSL extends AudioFloatConverter {
+
+ final int xbytes;
+
+ public AudioFloatConversion32xSL(int xbytes) {
+ this.xbytes = xbytes;
+ }
+
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ ix += xbytes;
+ int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
+ | ((in_buff[ix++] & 0xFF) << 16)
+ | ((in_buff[ix++] & 0xFF) << 24);
+ out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
+ for (int j = 0; j < xbytes; j++) {
+ out_buff[ox++] = 0;
+ }
+ out_buff[ox++] = (byte) x;
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) (x >>> 16);
+ out_buff[ox++] = (byte) (x >>> 24);
+ }
+ return out_buff;
+ }
+ }
+
+ // PCM 32+ bit, signed, big-endian
+ private static class AudioFloatConversion32xSB extends AudioFloatConverter {
+
+ final int xbytes;
+
+ public AudioFloatConversion32xSB(int xbytes) {
+ this.xbytes = xbytes;
+ }
+
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ int x = ((in_buff[ix++] & 0xFF) << 24)
+ | ((in_buff[ix++] & 0xFF) << 16)
+ | ((in_buff[ix++] & 0xFF) << 8)
+ | (in_buff[ix++] & 0xFF);
+ ix += xbytes;
+ out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
+ out_buff[ox++] = (byte) (x >>> 24);
+ out_buff[ox++] = (byte) (x >>> 16);
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) x;
+ for (int j = 0; j < xbytes; j++) {
+ out_buff[ox++] = 0;
+ }
+ }
+ return out_buff;
+ }
+ }
+
+ // PCM 32+ bit, unsigned, little-endian
+ private static class AudioFloatConversion32xUL extends AudioFloatConverter {
+
+ final int xbytes;
+
+ public AudioFloatConversion32xUL(int xbytes) {
+ this.xbytes = xbytes;
+ }
+
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ ix += xbytes;
+ int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
+ | ((in_buff[ix++] & 0xFF) << 16)
+ | ((in_buff[ix++] & 0xFF) << 24);
+ x -= 0x7FFFFFFF;
+ out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
+ x += 0x7FFFFFFF;
+ for (int j = 0; j < xbytes; j++) {
+ out_buff[ox++] = 0;
+ }
+ out_buff[ox++] = (byte) x;
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) (x >>> 16);
+ out_buff[ox++] = (byte) (x >>> 24);
+ }
+ return out_buff;
+ }
+ }
+
+ // PCM 32+ bit, unsigned, big-endian
+ private static class AudioFloatConversion32xUB extends AudioFloatConverter {
+
+ final int xbytes;
+
+ public AudioFloatConversion32xUB(int xbytes) {
+ this.xbytes = xbytes;
+ }
+
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < out_len; i++) {
+ int x = ((in_buff[ix++] & 0xFF) << 24) |
+ ((in_buff[ix++] & 0xFF) << 16) |
+ ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
+ ix += xbytes;
+ x -= 2147483647;
+ out_buff[ox++] = x * (1.0f / 2147483647.0f);
+ }
+ return out_buff;
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff, int out_offset) {
+ int ix = in_offset;
+ int ox = out_offset;
+ for (int i = 0; i < in_len; i++) {
+ int x = (int) (in_buff[ix++] * 2147483647.0);
+ x += 2147483647;
+ out_buff[ox++] = (byte) (x >>> 24);
+ out_buff[ox++] = (byte) (x >>> 16);
+ out_buff[ox++] = (byte) (x >>> 8);
+ out_buff[ox++] = (byte) x;
+ for (int j = 0; j < xbytes; j++) {
+ out_buff[ox++] = 0;
+ }
+ }
+ return out_buff;
+ }
+ }
+
+ public static AudioFloatConverter getConverter(AudioFormat format) {
+ AudioFloatConverter conv = null;
+ if (format.getFrameSize() == 0)
+ return null;
+ if (format.getFrameSize() !=
+ ((format.getSampleSizeInBits() + 7) / 8) * format.getChannels()) {
+ return null;
+ }
+ if (format.getEncoding().equals(Encoding.PCM_SIGNED)) {
+ if (format.isBigEndian()) {
+ if (format.getSampleSizeInBits() <= 8) {
+ conv = new AudioFloatConversion8S();
+ } else if (format.getSampleSizeInBits() > 8 &&
+ format.getSampleSizeInBits() <= 16) {
+ conv = new AudioFloatConversion16SB();
+ } else if (format.getSampleSizeInBits() > 16 &&
+ format.getSampleSizeInBits() <= 24) {
+ conv = new AudioFloatConversion24SB();
+ } else if (format.getSampleSizeInBits() > 24 &&
+ format.getSampleSizeInBits() <= 32) {
+ conv = new AudioFloatConversion32SB();
+ } else if (format.getSampleSizeInBits() > 32) {
+ conv = new AudioFloatConversion32xSB(((format
+ .getSampleSizeInBits() + 7) / 8) - 4);
+ }
+ } else {
+ if (format.getSampleSizeInBits() <= 8) {
+ conv = new AudioFloatConversion8S();
+ } else if (format.getSampleSizeInBits() > 8 &&
+ format.getSampleSizeInBits() <= 16) {
+ conv = new AudioFloatConversion16SL();
+ } else if (format.getSampleSizeInBits() > 16 &&
+ format.getSampleSizeInBits() <= 24) {
+ conv = new AudioFloatConversion24SL();
+ } else if (format.getSampleSizeInBits() > 24 &&
+ format.getSampleSizeInBits() <= 32) {
+ conv = new AudioFloatConversion32SL();
+ } else if (format.getSampleSizeInBits() > 32) {
+ conv = new AudioFloatConversion32xSL(((format
+ .getSampleSizeInBits() + 7) / 8) - 4);
+ }
+ }
+ } else if (format.getEncoding().equals(Encoding.PCM_UNSIGNED)) {
+ if (format.isBigEndian()) {
+ if (format.getSampleSizeInBits() <= 8) {
+ conv = new AudioFloatConversion8U();
+ } else if (format.getSampleSizeInBits() > 8 &&
+ format.getSampleSizeInBits() <= 16) {
+ conv = new AudioFloatConversion16UB();
+ } else if (format.getSampleSizeInBits() > 16 &&
+ format.getSampleSizeInBits() <= 24) {
+ conv = new AudioFloatConversion24UB();
+ } else if (format.getSampleSizeInBits() > 24 &&
+ format.getSampleSizeInBits() <= 32) {
+ conv = new AudioFloatConversion32UB();
+ } else if (format.getSampleSizeInBits() > 32) {
+ conv = new AudioFloatConversion32xUB(((
+ format.getSampleSizeInBits() + 7) / 8) - 4);
+ }
+ } else {
+ if (format.getSampleSizeInBits() <= 8) {
+ conv = new AudioFloatConversion8U();
+ } else if (format.getSampleSizeInBits() > 8 &&
+ format.getSampleSizeInBits() <= 16) {
+ conv = new AudioFloatConversion16UL();
+ } else if (format.getSampleSizeInBits() > 16 &&
+ format.getSampleSizeInBits() <= 24) {
+ conv = new AudioFloatConversion24UL();
+ } else if (format.getSampleSizeInBits() > 24 &&
+ format.getSampleSizeInBits() <= 32) {
+ conv = new AudioFloatConversion32UL();
+ } else if (format.getSampleSizeInBits() > 32) {
+ conv = new AudioFloatConversion32xUL(((
+ format.getSampleSizeInBits() + 7) / 8) - 4);
+ }
+ }
+ } else if (format.getEncoding().equals(PCM_FLOAT)) {
+ if (format.getSampleSizeInBits() == 32) {
+ if (format.isBigEndian())
+ conv = new AudioFloatConversion32B();
+ else
+ conv = new AudioFloatConversion32L();
+ } else if (format.getSampleSizeInBits() == 64) {
+ if (format.isBigEndian())
+ conv = new AudioFloatConversion64B();
+ else
+ conv = new AudioFloatConversion64L();
+ }
+
+ }
+
+ if ((format.getEncoding().equals(Encoding.PCM_SIGNED) ||
+ format.getEncoding().equals(Encoding.PCM_UNSIGNED)) &&
+ (format.getSampleSizeInBits() % 8 != 0)) {
+ conv = new AudioFloatLSBFilter(conv, format);
+ }
+
+ if (conv != null)
+ conv.format = format;
+ return conv;
+ }
+
+ private AudioFormat format;
+
+ public AudioFormat getFormat() {
+ return format;
+ }
+
+ public abstract float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_offset, int out_len);
+
+ public float[] toFloatArray(byte[] in_buff, float[] out_buff,
+ int out_offset, int out_len) {
+ return toFloatArray(in_buff, 0, out_buff, out_offset, out_len);
+ }
+
+ public float[] toFloatArray(byte[] in_buff, int in_offset,
+ float[] out_buff, int out_len) {
+ return toFloatArray(in_buff, in_offset, out_buff, 0, out_len);
+ }
+
+ public float[] toFloatArray(byte[] in_buff, float[] out_buff, int out_len) {
+ return toFloatArray(in_buff, 0, out_buff, 0, out_len);
+ }
+
+ public float[] toFloatArray(byte[] in_buff, float[] out_buff) {
+ return toFloatArray(in_buff, 0, out_buff, 0, out_buff.length);
+ }
+
+ public abstract byte[] toByteArray(float[] in_buff, int in_offset,
+ int in_len, byte[] out_buff, int out_offset);
+
+ public byte[] toByteArray(float[] in_buff, int in_len, byte[] out_buff,
+ int out_offset) {
+ return toByteArray(in_buff, 0, in_len, out_buff, out_offset);
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+ byte[] out_buff) {
+ return toByteArray(in_buff, in_offset, in_len, out_buff, 0);
+ }
+
+ public byte[] toByteArray(float[] in_buff, int in_len, byte[] out_buff) {
+ return toByteArray(in_buff, 0, in_len, out_buff, 0);
+ }
+
+ public byte[] toByteArray(float[] in_buff, byte[] out_buff) {
+ return toByteArray(in_buff, 0, in_buff.length, out_buff, 0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java Mon Jan 19 20:11:58 2009 +0300
@@ -0,0 +1,617 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.media.sound;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.AudioFormat.Encoding;
+import javax.sound.sampled.spi.FormatConversionProvider;
+
+/**
+ * This class is used to convert between 8,16,24,32 bit signed/unsigned
+ * big/litle endian fixed/floating stereo/mono/multi-channel audio streams and
+ * perform sample-rate conversion if needed.
+ *
+ * @author Karl Helgason
+ */
+public class AudioFloatFormatConverter extends FormatConversionProvider {
+
+ private static class AudioFloatFormatConverterInputStream extends
+ InputStream {
+ private AudioFloatConverter converter;
+
+ private AudioFloatInputStream stream;
+
+ private float[] readfloatbuffer;
+
+ private int fsize = 0;
+
+ public AudioFloatFormatConverterInputStream(AudioFormat targetFormat,
+ AudioFloatInputStream stream) {
+ this.stream = stream;
+ converter = AudioFloatConverter.getConverter(targetFormat);
+ fsize = ((targetFormat.getSampleSizeInBits() + 7) / 8);
+ }
+
+ public int read() throws IOException {
+ byte[] b = new byte[1];
+ int ret = read(b);
+ if (ret < 0)
+ return ret;
+ return b[0] & 0xFF;
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+
+ int fle