feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
import java.util.EventListener;
/**
* The <code>ControllerEventListener</code> interface should be implemented
* by classes whose instances need to be notified when a <code>Sequencer</code>
* has processed a requested type of MIDI control-change event.
* To register a <code>ControllerEventListener</code> object to receive such
* notifications, invoke the
* {@link Sequencer#addControllerEventListener(ControllerEventListener, int[])
* addControllerEventListener} method of <code>Sequencer</code>,
* specifying the types of MIDI controllers about which you are interested in
* getting control-change notifications.
*
* @see MidiChannel#controlChange(int, int)
*
* @author Kara Kytle
*/
public interface ControllerEventListener extends EventListener {
/**
* Invoked when a <code>Sequencer</code> has encountered and processed
* a control-change event of interest to this listener. The event passed
* in is a <code>ShortMessage</code> whose first data byte indicates
* the controller number and whose second data byte is the value to which
* the controller was set.
*
* @param event the control-change event that the sequencer encountered in
* the sequence it is processing
*
* @see Sequencer#addControllerEventListener(ControllerEventListener, int[])
* @see MidiChannel#controlChange(int, int)
* @see ShortMessage#getData1
* @see ShortMessage#getData2
*/
public void controlChange(ShortMessage event);
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 1999, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
import java.net.URL;
/**
* An instrument is a sound-synthesis algorithm with certain parameter
* settings, usually designed to emulate a specific real-world
* musical instrument or to achieve a specific sort of sound effect.
* Instruments are typically stored in collections called soundbanks.
* Before the instrument can be used to play notes, it must first be loaded
* onto a synthesizer, and then it must be selected for use on
* one or more channels, via a program-change command. MIDI notes
* that are subsequently received on those channels will be played using
* the sound of the selected instrument.
*
* @see Soundbank
* @see Soundbank#getInstruments
* @see Patch
* @see Synthesizer#loadInstrument(Instrument)
* @see MidiChannel#programChange(int, int)
* @author Kara Kytle
*/
public abstract class Instrument extends SoundbankResource {
/**
* Instrument patch
*/
private final Patch patch;
/**
* Constructs a new MIDI instrument from the specified <code>Patch</code>.
* When a subsequent request is made to load the
* instrument, the sound bank will search its contents for this instrument's <code>Patch</code>,
* and the instrument will be loaded into the synthesizer at the
* bank and program location indicated by the <code>Patch</code> object.
* @param soundbank sound bank containing the instrument
* @param patch the patch of this instrument
* @param name the name of this instrument
* @param dataClass the class used to represent the sample's data.
*
* @see Synthesizer#loadInstrument(Instrument)
*/
protected Instrument(Soundbank soundbank, Patch patch, String name, Class<?> dataClass) {
super(soundbank, name, dataClass);
this.patch = patch;
}
/**
* Obtains the <code>Patch</code> object that indicates the bank and program
* numbers where this instrument is to be stored in the synthesizer.
* @return this instrument's patch
*/
public Patch getPatch() {
return patch;
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* An <code>InvalidMidiDataException</code> indicates that inappropriate MIDI
* data was encountered. This often means that the data is invalid in and of
* itself, from the perspective of the MIDI specification. An example would
* be an undefined status byte. However, the exception might simply
* mean that the data was invalid in the context it was used, or that
* the object to which the data was given was unable to parse or use it.
* For example, a file reader might not be able to parse a Type 2 MIDI file, even
* though that format is defined in the MIDI specification.
*
* @author Kara Kytle
*/
public class InvalidMidiDataException extends Exception {
/**
* Constructs an <code>InvalidMidiDataException</code> with
* <code>null</code> for its error detail message.
*/
public InvalidMidiDataException() {
super();
}
/**
* Constructs an <code>InvalidMidiDataException</code> with the
* specified detail message.
*
* @param message the string to display as an error detail message
*/
public InvalidMidiDataException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
import java.util.EventListener;
/**
* The <code>MetaEventListener</code> interface should be implemented
* by classes whose instances need to be notified when a <code>{@link Sequencer}</code>
* has processed a <code>{@link MetaMessage}</code>.
* To register a <code>MetaEventListener</code> object to receive such
* notifications, pass it as the argument to the
* <code>{@link Sequencer#addMetaEventListener(MetaEventListener) addMetaEventListener}</code>
* method of <code>Sequencer</code>.
*
* @author Kara Kytle
*/
public interface MetaEventListener extends EventListener {
/**
* Invoked when a <code>{@link Sequencer}</code> has encountered and processed
* a <code>MetaMessage</code> in the <code>{@link Sequence}</code> it is processing.
* @param meta the meta-message that the sequencer encountered
*/
public void meta(MetaMessage meta);
}

View File

@@ -0,0 +1,244 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* A <code>MetaMessage</code> is a <code>{@link MidiMessage}</code> that is not meaningful to synthesizers, but
* that can be stored in a MIDI file and interpreted by a sequencer program.
* (See the discussion in the <code>MidiMessage</code>
* class description.) The Standard MIDI Files specification defines
* various types of meta-events, such as sequence number, lyric, cue point,
* and set tempo. There are also meta-events
* for such information as lyrics, copyrights, tempo indications, time and key
* signatures, markers, etc. For more information, see the Standard MIDI Files 1.0
* specification, which is part of the Complete MIDI 1.0 Detailed Specification
* published by the MIDI Manufacturer's Association
* (<a href = http://www.midi.org>http://www.midi.org</a>).
*
* <p>
* When data is being transported using MIDI wire protocol,
* a <code>{@link ShortMessage}</code> with the status value <code>0xFF</code> represents
* a system reset message. In MIDI files, this same status value denotes a <code>MetaMessage</code>.
* The types of meta-message are distinguished from each other by the first byte
* that follows the status byte <code>0xFF</code>. The subsequent bytes are data
* bytes. As with system exclusive messages, there are an arbitrary number of
* data bytes, depending on the type of <code>MetaMessage</code>.
*
* @see MetaEventListener
*
* @author David Rivas
* @author Kara Kytle
*/
public class MetaMessage extends MidiMessage {
// Status byte defines
/**
* Status byte for <code>MetaMessage</code> (0xFF, or 255), which is used
* in MIDI files. It has the same value as SYSTEM_RESET, which
* is used in the real-time "MIDI wire" protocol.
* @see MidiMessage#getStatus
*/
public static final int META = 0xFF; // 255
// Instance variables
/**
* The length of the actual message in the data array.
* This is used to determine how many bytes of the data array
* is the message, and how many are the status byte, the
* type byte, and the variable-length-int describing the
* length of the message.
*/
private int dataLength = 0;
/**
* Constructs a new <code>MetaMessage</code>. The contents of
* the message are not set here; use
* {@link #setMessage(int, byte[], int) setMessage}
* to set them subsequently.
*/
public MetaMessage() {
// Default meta message data: just the META status byte value
this(new byte[]{(byte) META, 0});
}
/**
* Constructs a new {@code MetaMessage} and sets the message parameters.
* The contents of the message can be changed by using
* the {@code setMessage} method.
*
* @param type meta-message type (must be less than 128)
* @param data the data bytes in the MIDI message
* @param length an amount of bytes in the {@code data} byte array;
* it should be non-negative and less than or equal to
* {@code data.length}
* @throws InvalidMidiDataException if the parameter values do not specify
* a valid MIDI meta message
* @see #setMessage(int, byte[], int)
* @see #getType()
* @see #getData()
* @since 1.7
*/
public MetaMessage(int type, byte[] data, int length)
throws InvalidMidiDataException {
super(null);
setMessage(type, data, length); // can throw InvalidMidiDataException
}
/**
* Constructs a new <code>MetaMessage</code>.
* @param data an array of bytes containing the complete message.
* The message data may be changed using the <code>setMessage</code>
* method.
* @see #setMessage
*/
protected MetaMessage(byte[] data) {
super(data);
//$$fb 2001-10-06: need to calculate dataLength. Fix for bug #4511796
if (data.length>=3) {
dataLength=data.length-3;
int pos=2;
while (pos<data.length && (data[pos] & 0x80)!=0) {
dataLength--; pos++;
}
}
}
/**
* Sets the message parameters for a <code>MetaMessage</code>.
* Since only one status byte value, <code>0xFF</code>, is allowed for meta-messages,
* it does not need to be specified here. Calls to <code>{@link MidiMessage#getStatus getStatus}</code> return
* <code>0xFF</code> for all meta-messages.
* <p>
* The <code>type</code> argument should be a valid value for the byte that
* follows the status byte in the <code>MetaMessage</code>. The <code>data</code> argument
* should contain all the subsequent bytes of the <code>MetaMessage</code>. In other words,
* the byte that specifies the type of <code>MetaMessage</code> is not considered a data byte.
*
* @param type meta-message type (must be less than 128)
* @param data the data bytes in the MIDI message
* @param length the number of bytes in the <code>data</code>
* byte array
* @throws InvalidMidiDataException if the
* parameter values do not specify a valid MIDI meta message
*/
public void setMessage(int type, byte[] data, int length) throws InvalidMidiDataException {
if (type >= 128 || type < 0) {
throw new InvalidMidiDataException("Invalid meta event with type " + type);
}
if ((length > 0 && length > data.length) || length < 0) {
throw new InvalidMidiDataException("length out of bounds: "+length);
}
this.length = 2 + getVarIntLength(length) + length;
this.dataLength = length;
this.data = new byte[this.length];
this.data[0] = (byte) META; // status value for MetaMessages (meta events)
this.data[1] = (byte) type; // MetaMessage type
writeVarInt(this.data, 2, length); // write the length as a variable int
if (length > 0) {
System.arraycopy(data, 0, this.data, this.length - this.dataLength, this.dataLength);
}
}
/**
* Obtains the type of the <code>MetaMessage</code>.
* @return an integer representing the <code>MetaMessage</code> type
*/
public int getType() {
if (length>=2) {
return data[1] & 0xFF;
}
return 0;
}
/**
* Obtains a copy of the data for the meta message. The returned
* array of bytes does not include the status byte or the message
* length data. The length of the data for the meta message is
* the length of the array. Note that the length of the entire
* message includes the status byte and the meta message type
* byte, and therefore may be longer than the returned array.
* @return array containing the meta message data.
* @see MidiMessage#getLength
*/
public byte[] getData() {
byte[] returnedArray = new byte[dataLength];
System.arraycopy(data, (length - dataLength), returnedArray, 0, dataLength);
return returnedArray;
}
/**
* Creates a new object of the same class and with the same contents
* as this object.
* @return a clone of this instance
*/
public Object clone() {
byte[] newData = new byte[length];
System.arraycopy(data, 0, newData, 0, newData.length);
MetaMessage event = new MetaMessage(newData);
return event;
}
// HELPER METHODS
private int getVarIntLength(long value) {
int length = 0;
do {
value = value >> 7;
length++;
} while (value > 0);
return length;
}
private final static long mask = 0x7F;
private void writeVarInt(byte[] data, int off, long value) {
int shift=63; // number of bitwise left-shifts of mask
// first screen out leading zeros
while ((shift > 0) && ((value & (mask << shift)) == 0)) shift-=7;
// then write actual values
while (shift > 0) {
data[off++]=(byte) (((value & (mask << shift)) >> shift) | 0x80);
shift-=7;
}
data[off] = (byte) (value & mask);
}
}

View File

@@ -0,0 +1,537 @@
/*
* Copyright (c) 1998, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* A <code>MidiChannel</code> object represents a single MIDI channel.
* Generally, each <code>MidiChannel</code> method processes a like-named MIDI
* "channel voice" or "channel mode" message as defined by the MIDI specification. However,
* <code>MidiChannel</code> adds some "get" methods that retrieve the value
* most recently set by one of the standard MIDI channel messages. Similarly,
* methods for per-channel solo and mute have been added.
* <p>
* A <code>{@link Synthesizer}</code> object has a collection
* of <code>MidiChannels</code>, usually one for each of the 16 channels
* prescribed by the MIDI 1.0 specification. The <code>Synthesizer</code>
* generates sound when its <code>MidiChannels</code> receive
* <code>noteOn</code> messages.
* <p>
* See the MIDI 1.0 Specification for more information about the prescribed
* behavior of the MIDI channel messages, which are not exhaustively
* documented here. The specification is titled <code>MIDI Reference:
* The Complete MIDI 1.0 Detailed Specification</code>, and is published by
* the MIDI Manufacturer's Association (<a href = http://www.midi.org>
* http://www.midi.org</a>).
* <p>
* MIDI was originally a protocol for reporting the gestures of a keyboard
* musician. This genesis is visible in the <code>MidiChannel</code> API, which
* preserves such MIDI concepts as key number, key velocity, and key pressure.
* It should be understood that the MIDI data does not necessarily originate
* with a keyboard player (the source could be a different kind of musician, or
* software). Some devices might generate constant values for velocity
* and pressure, regardless of how the note was performed.
* Also, the MIDI specification often leaves it up to the
* synthesizer to use the data in the way the implementor sees fit. For
* example, velocity data need not always be mapped to volume and/or brightness.
*
* @see Synthesizer#getChannels
*
* @author David Rivas
* @author Kara Kytle
*/
public interface MidiChannel {
/**
* Starts the specified note sounding. The key-down velocity
* usually controls the note's volume and/or brightness.
* If <code>velocity</code> is zero, this method instead acts like
* {@link #noteOff(int)}, terminating the note.
*
* @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C)
* @param velocity the speed with which the key was depressed
*
* @see #noteOff(int, int)
*/
public void noteOn(int noteNumber, int velocity);
/**
* Turns the specified note off. The key-up velocity, if not ignored, can
* be used to affect how quickly the note decays.
* In any case, the note might not die away instantaneously; its decay
* rate is determined by the internals of the <code>Instrument</code>.
* If the Hold Pedal (a controller; see
* {@link #controlChange(int, int) controlChange})
* is down, the effect of this method is deferred until the pedal is
* released.
*
*
* @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C)
* @param velocity the speed with which the key was released
*
* @see #noteOff(int)
* @see #noteOn
* @see #allNotesOff
* @see #allSoundOff
*/
public void noteOff(int noteNumber, int velocity);
/**
* Turns the specified note off.
*
* @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C)
*
* @see #noteOff(int, int)
*/
public void noteOff(int noteNumber);
/**
* Reacts to a change in the specified note's key pressure.
* Polyphonic key pressure
* allows a keyboard player to press multiple keys simultaneously, each
* with a different amount of pressure. The pressure, if not ignored,
* is typically used to vary such features as the volume, brightness,
* or vibrato of the note.
*
* It is possible that the underlying synthesizer
* does not support this MIDI message. In order
* to verify that <code>setPolyPressure</code>
* was successful, use <code>getPolyPressure</code>.
*
* @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C)
* @param pressure value for the specified key, from 0 to 127 (127 =
* maximum pressure)
*
* @see #getPolyPressure(int)
*/
public void setPolyPressure(int noteNumber, int pressure);
/**
* Obtains the pressure with which the specified key is being depressed.
*
* @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C)
*
* If the device does not support setting poly pressure,
* this method always returns 0. Calling
* <code>setPolyPressure</code> will have no effect then.
*
* @return the amount of pressure for that note, from 0 to 127
* (127 = maximum pressure)
*
* @see #setPolyPressure(int, int)
*/
public int getPolyPressure(int noteNumber);
/**
* Reacts to a change in the keyboard pressure. Channel
* pressure indicates how hard the keyboard player is depressing
* the entire keyboard. This can be the maximum or
* average of the per-key pressure-sensor values, as set by
* <code>setPolyPressure</code>. More commonly, it is a measurement of
* a single sensor on a device that doesn't implement polyphonic key
* pressure. Pressure can be used to control various aspects of the sound,
* as described under {@link #setPolyPressure(int, int) setPolyPressure}.
*
* It is possible that the underlying synthesizer
* does not support this MIDI message. In order
* to verify that <code>setChannelPressure</code>
* was successful, use <code>getChannelPressure</code>.
*
* @param pressure the pressure with which the keyboard is being depressed,
* from 0 to 127 (127 = maximum pressure)
* @see #setPolyPressure(int, int)
* @see #getChannelPressure
*/
public void setChannelPressure(int pressure);
/**
* Obtains the channel's keyboard pressure.
* If the device does not support setting channel pressure,
* this method always returns 0. Calling
* <code>setChannelPressure</code> will have no effect then.
*
* @return the amount of pressure for that note,
* from 0 to 127 (127 = maximum pressure)
*
* @see #setChannelPressure(int)
*/
public int getChannelPressure();
/**
* Reacts to a change in the specified controller's value. A controller
* is some control other than a keyboard key, such as a
* switch, slider, pedal, wheel, or breath-pressure sensor.
* The MIDI 1.0 Specification provides standard numbers for typical
* controllers on MIDI devices, and describes the intended effect
* for some of the controllers.
* The way in which an
* <code>Instrument</code> reacts to a controller change may be
* specific to the <code>Instrument</code>.
* <p>
* The MIDI 1.0 Specification defines both 7-bit controllers
* and 14-bit controllers. Continuous controllers, such
* as wheels and sliders, typically have 14 bits (two MIDI bytes),
* while discrete controllers, such as switches, typically have 7 bits
* (one MIDI byte). Refer to the specification to see the
* expected resolution for each type of control.
* <p>
* Controllers 64 through 95 (0x40 - 0x5F) allow 7-bit precision.
* The value of a 7-bit controller is set completely by the
* <code>value</code> argument. An additional set of controllers
* provide 14-bit precision by using two controller numbers, one
* for the most significant 7 bits and another for the least significant
* 7 bits. Controller numbers 0 through 31 (0x00 - 0x1F) control the
* most significant 7 bits of 14-bit controllers; controller numbers
* 32 through 63 (0x20 - 0x3F) control the least significant 7 bits of
* these controllers. For example, controller number 7 (0x07) controls
* the upper 7 bits of the channel volume controller, and controller
* number 39 (0x27) controls the lower 7 bits.
* The value of a 14-bit controller is determined
* by the interaction of the two halves. When the most significant 7 bits
* of a controller are set (using controller numbers 0 through 31), the
* lower 7 bits are automatically set to 0. The corresponding controller
* number for the lower 7 bits may then be used to further modulate the
* controller value.
*
* It is possible that the underlying synthesizer
* does not support a specific controller message. In order
* to verify that a call to <code>controlChange</code>
* was successful, use <code>getController</code>.
*
* @param controller the controller number (0 to 127; see the MIDI
* 1.0 Specification for the interpretation)
* @param value the value to which the specified controller is changed (0 to 127)
*
* @see #getController(int)
*/
public void controlChange(int controller, int value);
/**
* Obtains the current value of the specified controller. The return
* value is represented with 7 bits. For 14-bit controllers, the MSB and
* LSB controller value needs to be obtained separately. For example,
* the 14-bit value of the volume controller can be calculated by
* multiplying the value of controller 7 (0x07, channel volume MSB)
* with 128 and adding the
* value of controller 39 (0x27, channel volume LSB).
*
* If the device does not support setting a specific controller,
* this method returns 0 for that controller.
* Calling <code>controlChange</code> will have no effect then.
*
* @param controller the number of the controller whose value is desired.
* The allowed range is 0-127; see the MIDI
* 1.0 Specification for the interpretation.
*
* @return the current value of the specified controller (0 to 127)
*
* @see #controlChange(int, int)
*/
public int getController(int controller);
/**
* Changes a program (patch). This selects a specific
* instrument from the currently selected bank of instruments.
* <p>
* The MIDI specification does not
* dictate whether notes that are already sounding should switch
* to the new instrument (timbre) or continue with their original timbre
* until terminated by a note-off.
* <p>
* The program number is zero-based (expressed from 0 to 127).
* Note that MIDI hardware displays and literature about MIDI
* typically use the range 1 to 128 instead.
*
* It is possible that the underlying synthesizer
* does not support a specific program. In order
* to verify that a call to <code>programChange</code>
* was successful, use <code>getProgram</code>.
*
* @param program the program number to switch to (0 to 127)
*
* @see #programChange(int, int)
* @see #getProgram()
*/
public void programChange(int program);
/**
* Changes the program using bank and program (patch) numbers.
*
* It is possible that the underlying synthesizer
* does not support a specific bank, or program. In order
* to verify that a call to <code>programChange</code>
* was successful, use <code>getProgram</code> and
* <code>getController</code>.
* Since banks are changed by way of control changes,
* you can verify the current bank with the following
* statement:
* <pre>
* int bank = (getController(0) * 128)
* + getController(32);
* </pre>
*
* @param bank the bank number to switch to (0 to 16383)
* @param program the program (patch) to use in the specified bank (0 to 127)
* @see #programChange(int)
* @see #getProgram()
*/
public void programChange(int bank, int program);
/**
* Obtains the current program number for this channel.
* @return the program number of the currently selected patch
* @see Patch#getProgram
* @see Synthesizer#loadInstrument
* @see #programChange(int)
*/
public int getProgram();
/**
* Changes the pitch offset for all notes on this channel.
* This affects all currently sounding notes as well as subsequent ones.
* (For pitch bend to cease, the value needs to be reset to the
* center position.)
* <p> The MIDI specification
* stipulates that pitch bend be a 14-bit value, where zero
* is maximum downward bend, 16383 is maximum upward bend, and
* 8192 is the center (no pitch bend). The actual
* amount of pitch change is not specified; it can be changed by
* a pitch-bend sensitivity setting. However, the General MIDI
* specification says that the default range should be two semitones
* up and down from center.
*
* It is possible that the underlying synthesizer
* does not support this MIDI message. In order
* to verify that <code>setPitchBend</code>
* was successful, use <code>getPitchBend</code>.
*
* @param bend the amount of pitch change, as a nonnegative 14-bit value
* (8192 = no bend)
*
* @see #getPitchBend
*/
public void setPitchBend(int bend);
/**
* Obtains the upward or downward pitch offset for this channel.
* If the device does not support setting pitch bend,
* this method always returns 8192. Calling
* <code>setPitchBend</code> will have no effect then.
*
* @return bend amount, as a nonnegative 14-bit value (8192 = no bend)
*
* @see #setPitchBend(int)
*/
public int getPitchBend();
/**
* Resets all the implemented controllers to their default values.
*
* @see #controlChange(int, int)
*/
public void resetAllControllers();
/**
* Turns off all notes that are currently sounding on this channel.
* The notes might not die away instantaneously; their decay
* rate is determined by the internals of the <code>Instrument</code>.
* If the Hold Pedal controller (see
* {@link #controlChange(int, int) controlChange})
* is down, the effect of this method is deferred until the pedal is
* released.
*
* @see #allSoundOff
* @see #noteOff(int)
*/
public void allNotesOff();
/**
* Immediately turns off all sounding notes on this channel, ignoring the
* state of the Hold Pedal and the internal decay rate of the current
* <code>Instrument</code>.
*
* @see #allNotesOff
*/
public void allSoundOff();
/**
* Turns local control on or off. The default is for local control
* to be on. The "on" setting means that if a device is capable
* of both synthesizing sound and transmitting MIDI messages,
* it will synthesize sound in response to the note-on and
* note-off messages that it itself transmits. It will also respond
* to messages received from other transmitting devices.
* The "off" setting means that the synthesizer will ignore its
* own transmitted MIDI messages, but not those received from other devices.
*
* It is possible that the underlying synthesizer
* does not support local control. In order
* to verify that a call to <code>localControl</code>
* was successful, check the return value.
*
* @param on <code>true</code> to turn local control on, <code>false</code>
* to turn local control off
* @return the new local-control value, or false
* if local control is not supported
*
*/
public boolean localControl(boolean on);
/**
* Turns mono mode on or off. In mono mode, the channel synthesizes
* only one note at a time. In poly mode (identical to mono mode off),
* the channel can synthesize multiple notes simultaneously.
* The default is mono off (poly mode on).
* <p>
* "Mono" is short for the word "monophonic," which in this context
* is opposed to the word "polyphonic" and refers to a single synthesizer
* voice per MIDI channel. It
* has nothing to do with how many audio channels there might be
* (as in "monophonic" versus "stereophonic" recordings).
*
* It is possible that the underlying synthesizer
* does not support mono mode. In order
* to verify that a call to <code>setMono</code>
* was successful, use <code>getMono</code>.
*
* @param on <code>true</code> to turn mono mode on, <code>false</code> to
* turn it off (which means turning poly mode on).
*
* @see #getMono
* @see VoiceStatus
*/
public void setMono(boolean on);
/**
* Obtains the current mono/poly mode.
* Synthesizers that do not allow changing mono/poly mode
* will always return the same value, regardless
* of calls to <code>setMono</code>.
* @return <code>true</code> if mono mode is on, otherwise
* <code>false</code> (meaning poly mode is on).
*
* @see #setMono(boolean)
*/
public boolean getMono();
/**
* Turns omni mode on or off. In omni mode, the channel responds
* to messages sent on all channels. When omni is off, the channel
* responds only to messages sent on its channel number.
* The default is omni off.
*
* It is possible that the underlying synthesizer
* does not support omni mode. In order
* to verify that <code>setOmni</code>
* was successful, use <code>getOmni</code>.
*
* @param on <code>true</code> to turn omni mode on, <code>false</code> to
* turn it off.
*
* @see #getOmni
* @see VoiceStatus
*/
public void setOmni(boolean on);
/**
* Obtains the current omni mode.
* Synthesizers that do not allow changing the omni mode
* will always return the same value, regardless
* of calls to <code>setOmni</code>.
* @return <code>true</code> if omni mode is on, otherwise
* <code>false</code> (meaning omni mode is off).
*
* @see #setOmni(boolean)
*/
public boolean getOmni();
/**
* Sets the mute state for this channel. A value of
* <code>true</code> means the channel is to be muted, <code>false</code>
* means the channel can sound (if other channels are not soloed).
* <p>
* Unlike {@link #allSoundOff()}, this method
* applies to only a specific channel, not to all channels. Further, it
* silences not only currently sounding notes, but also subsequently
* received notes.
*
* It is possible that the underlying synthesizer
* does not support muting channels. In order
* to verify that a call to <code>setMute</code>
* was successful, use <code>getMute</code>.
*
* @param mute the new mute state
*
* @see #getMute
* @see #setSolo(boolean)
*/
public void setMute(boolean mute);
/**
* Obtains the current mute state for this channel.
* If the underlying synthesizer does not support
* muting this channel, this method always returns
* <code>false</code>.
*
* @return <code>true</code> the channel is muted,
* or <code>false</code> if not
*
* @see #setMute(boolean)
*/
public boolean getMute();
/**
* Sets the solo state for this channel.
* If <code>solo</code> is <code>true</code> only this channel
* and other soloed channels will sound. If <code>solo</code>
* is <code>false</code> then only other soloed channels will
* sound, unless no channels are soloed, in which case all
* unmuted channels will sound.
*
* It is possible that the underlying synthesizer
* does not support solo channels. In order
* to verify that a call to <code>setSolo</code>
* was successful, use <code>getSolo</code>.
*
* @param soloState new solo state for the channel
* @see #getSolo()
*/
public void setSolo(boolean soloState);
/**
* Obtains the current solo state for this channel.
* If the underlying synthesizer does not support
* solo on this channel, this method always returns
* <code>false</code>.
*
* @return <code>true</code> the channel is solo,
* or <code>false</code> if not
*
* @see #setSolo(boolean)
*/
public boolean getSolo();
}

View File

@@ -0,0 +1,393 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
import java.util.List;
/**
* <code>MidiDevice</code> is the base interface for all MIDI devices.
* Common devices include synthesizers, sequencers, MIDI input ports, and MIDI
* output ports.
*
* <p>A <code>MidiDevice</code> can be a transmitter or a receiver of
* MIDI events, or both. Therefore, it can provide {@link Transmitter}
* or {@link Receiver} instances (or both). Typically, MIDI IN ports
* provide transmitters, MIDI OUT ports and synthesizers provide
* receivers. A Sequencer typically provides transmitters for playback
* and receivers for recording.
*
* <p>A <code>MidiDevice</code> can be opened and closed explicitly as
* well as implicitly. Explicit opening is accomplished by calling
* {@link #open}, explicit closing is done by calling {@link
* #close} on the <code>MidiDevice</code> instance.
* If an application opens a <code>MidiDevice</code>
* explicitly, it has to close it explicitly to free system resources
* and enable the application to exit cleanly. Implicit opening is
* done by calling {@link javax.sound.midi.MidiSystem#getReceiver
* MidiSystem.getReceiver} and {@link
* javax.sound.midi.MidiSystem#getTransmitter
* MidiSystem.getTransmitter}. The <code>MidiDevice</code> used by
* <code>MidiSystem.getReceiver</code> and
* <code>MidiSystem.getTransmitter</code> is implementation-dependant
* unless the properties <code>javax.sound.midi.Receiver</code>
* and <code>javax.sound.midi.Transmitter</code> are used (see the
* description of properties to select default providers in
* {@link javax.sound.midi.MidiSystem}). A <code>MidiDevice</code>
* that was opened implicitly, is closed implicitly by closing the
* <code>Receiver</code> or <code>Transmitter</code> that resulted in
* opening it. If more than one implicitly opening
* <code>Receiver</code> or <code>Transmitter</code> were obtained by
* the application, the device is closed after the last
* <code>Receiver</code> or <code>Transmitter</code> has been
* closed. On the other hand, calling <code>getReceiver</code> or
* <code>getTransmitter</code> on the device instance directly does
* not open the device implicitly. Closing these
* <code>Transmitter</code>s and <code>Receiver</code>s does not close
* the device implicitly. To use a device with <code>Receiver</code>s
* or <code>Transmitter</code>s obtained this way, the device has to
* be opened and closed explicitly.
*
* <p>If implicit and explicit opening and closing are mixed on the
* same <code>MidiDevice</code> instance, the following rules apply:
*
* <ul>
* <li>After an explicit open (either before or after implicit
* opens), the device will not be closed by implicit closing. The only
* way to close an explicitly opened device is an explicit close.</li>
*
* <li>An explicit close always closes the device, even if it also has
* been opened implicitly. A subsequent implicit close has no further
* effect.</li>
* </ul>
*
* To detect if a MidiDevice represents a hardware MIDI port, the
* following programming technique can be used:
*
* <pre>{@code
* MidiDevice device = ...;
* if ( ! (device instanceof Sequencer) && ! (device instanceof Synthesizer)) {
* // we're now sure that device represents a MIDI port
* // ...
* }
* }</pre>
*
* <p>
* A <code>MidiDevice</code> includes a <code>{@link MidiDevice.Info}</code> object
* to provide manufacturer information and so on.
*
* @see Synthesizer
* @see Sequencer
* @see Receiver
* @see Transmitter
*
* @author Kara Kytle
* @author Florian Bomers
*/
public interface MidiDevice extends AutoCloseable {
/**
* Obtains information about the device, including its Java class and
* <code>Strings</code> containing its name, vendor, and description.
*
* @return device info
*/
public Info getDeviceInfo();
/**
* Opens the device, indicating that it should now acquire any
* system resources it requires and become operational.
*
* <p>An application opening a device explicitly with this call
* has to close the device by calling {@link #close}. This is
* necessary to release system resources and allow applications to
* exit cleanly.
*
* <p>
* Note that some devices, once closed, cannot be reopened. Attempts
* to reopen such a device will always result in a MidiUnavailableException.
*
* @throws MidiUnavailableException thrown if the device cannot be
* opened due to resource restrictions.
* @throws SecurityException thrown if the device cannot be
* opened due to security restrictions.
*
* @see #close
* @see #isOpen
*/
public void open() throws MidiUnavailableException;
/**
* Closes the device, indicating that the device should now release
* any system resources it is using.
*
* <p>All <code>Receiver</code> and <code>Transmitter</code> instances
* open from this device are closed. This includes instances retrieved
* via <code>MidiSystem</code>.
*
* @see #open
* @see #isOpen
*/
public void close();
/**
* Reports whether the device is open.
*
* @return <code>true</code> if the device is open, otherwise
* <code>false</code>
* @see #open
* @see #close
*/
public boolean isOpen();
/**
* Obtains the current time-stamp of the device, in microseconds.
* If a device supports time-stamps, it should start counting at
* 0 when the device is opened and continue incrementing its
* time-stamp in microseconds until the device is closed.
* If it does not support time-stamps, it should always return
* -1.
* @return the current time-stamp of the device in microseconds,
* or -1 if time-stamping is not supported by the device.
*/
public long getMicrosecondPosition();
/**
* Obtains the maximum number of MIDI IN connections available on this
* MIDI device for receiving MIDI data.
* @return maximum number of MIDI IN connections,
* or -1 if an unlimited number of connections is available.
*/
public int getMaxReceivers();
/**
* Obtains the maximum number of MIDI OUT connections available on this
* MIDI device for transmitting MIDI data.
* @return maximum number of MIDI OUT connections,
* or -1 if an unlimited number of connections is available.
*/
public int getMaxTransmitters();
/**
* Obtains a MIDI IN receiver through which the MIDI device may receive
* MIDI data. The returned receiver must be closed when the application
* has finished using it.
*
* <p>Usually the returned receiver implements
* the {@code MidiDeviceReceiver} interface.
*
* <p>Obtaining a <code>Receiver</code> with this method does not
* open the device. To be able to use the device, it has to be
* opened explicitly by calling {@link #open}. Also, closing the
* <code>Receiver</code> does not close the device. It has to be
* closed explicitly by calling {@link #close}.
*
* @return a receiver for the device.
* @throws MidiUnavailableException thrown if a receiver is not available
* due to resource restrictions
* @see Receiver#close()
*/
public Receiver getReceiver() throws MidiUnavailableException;
/**
* Returns all currently active, non-closed receivers
* connected with this MidiDevice.
* A receiver can be removed
* from the device by closing it.
*
* <p>Usually the returned receivers implement
* the {@code MidiDeviceReceiver} interface.
*
* @return an unmodifiable list of the open receivers
* @since 1.5
*/
List<Receiver> getReceivers();
/**
* Obtains a MIDI OUT connection from which the MIDI device will transmit
* MIDI data The returned transmitter must be closed when the application
* has finished using it.
*
* <p>Usually the returned transmitter implements
* the {@code MidiDeviceTransmitter} interface.
*
* <p>Obtaining a <code>Transmitter</code> with this method does not
* open the device. To be able to use the device, it has to be
* opened explicitly by calling {@link #open}. Also, closing the
* <code>Transmitter</code> does not close the device. It has to be
* closed explicitly by calling {@link #close}.
*
* @return a MIDI OUT transmitter for the device.
* @throws MidiUnavailableException thrown if a transmitter is not available
* due to resource restrictions
* @see Transmitter#close()
*/
public Transmitter getTransmitter() throws MidiUnavailableException;
/**
* Returns all currently active, non-closed transmitters
* connected with this MidiDevice.
* A transmitter can be removed
* from the device by closing it.
*
* <p>Usually the returned transmitters implement
* the {@code MidiDeviceTransmitter} interface.
*
* @return an unmodifiable list of the open transmitters
* @since 1.5
*/
List<Transmitter> getTransmitters();
/**
* A <code>MidiDevice.Info</code> object contains assorted
* data about a <code>{@link MidiDevice}</code>, including its
* name, the company who created it, and descriptive text.
*
* @see MidiDevice#getDeviceInfo
*/
public static class Info {
/**
* The device's name.
*/
private String name;
/**
* The name of the company who provides the device.
*/
private String vendor;
/**
* A description of the device.
*/
private String description;
/**
* Device version.
*/
private String version;
/**
* Constructs a device info object.
*
* @param name the name of the device
* @param vendor the name of the company who provides the device
* @param description a description of the device
* @param version version information for the device
*/
protected Info(String name, String vendor, String description, String version) {
this.name = name;
this.vendor = vendor;
this.description = description;
this.version = version;
}
/**
* Reports whether two objects are equal.
* Returns <code>true</code> if the objects are identical.
* @param obj the reference object with which to compare this
* object
* @return <code>true</code> if this object is the same as the
* <code>obj</code> argument; <code>false</code> otherwise
*/
public final boolean equals(Object obj) {
return super.equals(obj);
}
/**
* Finalizes the hashcode method.
*/
public final int hashCode() {
return super.hashCode();
}
/**
* Obtains the name of the device.
*
* @return a string containing the device's name
*/
public final String getName() {
return name;
}
/**
* Obtains the name of the company who supplies the device.
* @return device the vendor's name
*/
public final String getVendor() {
return vendor;
}
/**
* Obtains the description of the device.
* @return a description of the device
*/
public final String getDescription() {
return description;
}
/**
* Obtains the version of the device.
* @return textual version information for the device.
*/
public final String getVersion() {
return version;
}
/**
* Provides a string representation of the device information.
* @return a description of the info object
*/
public final String toString() {
return name;
}
} // class Info
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* <p>{@code MidiDeviceReceiver} is a {@code Receiver} which represents
* a MIDI input connector of a {@code MidiDevice}
* (see {@link MidiDevice#getReceiver()}).
*
* @since 1.7
*/
public interface MidiDeviceReceiver extends Receiver {
/**
* Obtains a MidiDevice object which is an owner of this Receiver.
* @return a MidiDevice object which is an owner of this Receiver
*/
public MidiDevice getMidiDevice();
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* <p>{@code MidiDeviceTransmitter} is a {@code Transmitter} which represents
* a MIDI input connector of a {@code MidiDevice}
* (see {@link MidiDevice#getTransmitter()}).
*
* @since 1.7
*/
public interface MidiDeviceTransmitter extends Transmitter {
/**
* Obtains a MidiDevice object which is an owner of this Transmitter.
* @return a MidiDevice object which is an owner of this Transmitter
*/
public MidiDevice getMidiDevice();
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* MIDI events contain a MIDI message and a corresponding time-stamp
* expressed in ticks, and can represent the MIDI event information
* stored in a MIDI file or a <code>{@link Sequence}</code> object. The
* duration of a tick is specified by the timing information contained
* in the MIDI file or <code>Sequence</code> object.
* <p>
* In Java Sound, <code>MidiEvent</code> objects are typically contained in a
* <code>{@link Track}</code>, and <code>Tracks</code> are likewise
* contained in a <code>Sequence</code>.
*
*
* @author David Rivas
* @author Kara Kytle
*/
public class MidiEvent {
// Instance variables
/**
* The MIDI message for this event.
*/
private final MidiMessage message;
/**
* The tick value for this event.
*/
private long tick;
/**
* Constructs a new <code>MidiEvent</code>.
* @param message the MIDI message contained in the event
* @param tick the time-stamp for the event, in MIDI ticks
*/
public MidiEvent(MidiMessage message, long tick) {
this.message = message;
this.tick = tick;
}
/**
* Obtains the MIDI message contained in the event.
* @return the MIDI message
*/
public MidiMessage getMessage() {
return message;
}
/**
* Sets the time-stamp for the event, in MIDI ticks
* @param tick the new time-stamp, in MIDI ticks
*/
public void setTick(long tick) {
this.tick = tick;
}
/**
* Obtains the time-stamp for the event, in MIDI ticks
* @return the time-stamp for the event, in MIDI ticks
*/
public long getTick() {
return tick;
}
}

View File

@@ -0,0 +1,304 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
import java.io.InputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* A <code>MidiFileFormat</code> object encapsulates a MIDI file's
* type, as well as its length and timing information.
*
* <p>A <code>MidiFileFormat</code> object can
* include a set of properties. A property is a pair of key and value:
* the key is of type <code>String</code>, the associated property
* value is an arbitrary object.
* Properties specify additional informational
* meta data (like a author, or copyright).
* Properties are optional information, and file reader and file
* writer implementations are not required to provide or
* recognize properties.
*
* <p>The following table lists some common properties that should
* be used in implementations:
*
* <table border=1>
<caption>MIDI File Format Properties</caption>
* <tr>
* <th>Property key</th>
* <th>Value type</th>
* <th>Description</th>
* </tr>
* <tr>
* <td>&quot;author&quot;</td>
* <td>{@link java.lang.String String}</td>
* <td>name of the author of this file</td>
* </tr>
* <tr>
* <td>&quot;title&quot;</td>
* <td>{@link java.lang.String String}</td>
* <td>title of this file</td>
* </tr>
* <tr>
* <td>&quot;copyright&quot;</td>
* <td>{@link java.lang.String String}</td>
* <td>copyright message</td>
* </tr>
* <tr>
* <td>&quot;date&quot;</td>
* <td>{@link java.util.Date Date}</td>
* <td>date of the recording or release</td>
* </tr>
* <tr>
* <td>&quot;comment&quot;</td>
* <td>{@link java.lang.String String}</td>
* <td>an arbitrary text</td>
* </tr>
* </table>
*
* @see MidiSystem#getMidiFileFormat(java.io.File)
* @see Sequencer#setSequence(java.io.InputStream stream)
*
* @author Kara Kytle
* @author Florian Bomers
*/
public class MidiFileFormat {
/**
* Represents unknown length.
* @see #getByteLength
* @see #getMicrosecondLength
*/
public static final int UNKNOWN_LENGTH = -1;
/**
* The type of MIDI file.
*/
protected int type;
/**
* The division type of the MIDI file.
*
* @see Sequence#PPQ
* @see Sequence#SMPTE_24
* @see Sequence#SMPTE_25
* @see Sequence#SMPTE_30DROP
* @see Sequence#SMPTE_30
*/
protected float divisionType;
/**
* The timing resolution of the MIDI file.
*/
protected int resolution;
/**
* The length of the MIDI file in bytes.
*/
protected int byteLength;
/**
* The duration of the MIDI file in microseconds.
*/
protected long microsecondLength;
/** The set of properties */
private HashMap<String, Object> properties;
/**
* Constructs a <code>MidiFileFormat</code>.
*
* @param type the MIDI file type (0, 1, or 2)
* @param divisionType the timing division type (PPQ or one of the SMPTE types)
* @param resolution the timing resolution
* @param bytes the length of the MIDI file in bytes, or UNKNOWN_LENGTH if not known
* @param microseconds the duration of the file in microseconds, or UNKNOWN_LENGTH if not known
* @see #UNKNOWN_LENGTH
* @see Sequence#PPQ
* @see Sequence#SMPTE_24
* @see Sequence#SMPTE_25
* @see Sequence#SMPTE_30DROP
* @see Sequence#SMPTE_30
*/
public MidiFileFormat(int type, float divisionType, int resolution, int bytes, long microseconds) {
this.type = type;
this.divisionType = divisionType;
this.resolution = resolution;
this.byteLength = bytes;
this.microsecondLength = microseconds;
this.properties = null;
}
/**
* Construct a <code>MidiFileFormat</code> with a set of properties.
*
* @param type the MIDI file type (0, 1, or 2)
* @param divisionType the timing division type
* (PPQ or one of the SMPTE types)
* @param resolution the timing resolution
* @param bytes the length of the MIDI file in bytes,
* or UNKNOWN_LENGTH if not known
* @param microseconds the duration of the file in microseconds,
* or UNKNOWN_LENGTH if not known
* @param properties a <code>Map&lt;String,Object&gt;</code> object
* with properties
*
* @see #UNKNOWN_LENGTH
* @see Sequence#PPQ
* @see Sequence#SMPTE_24
* @see Sequence#SMPTE_25
* @see Sequence#SMPTE_30DROP
* @see Sequence#SMPTE_30
* @since 1.5
*/
public MidiFileFormat(int type, float divisionType,
int resolution, int bytes,
long microseconds, Map<String, Object> properties) {
this(type, divisionType, resolution, bytes, microseconds);
this.properties = new HashMap<String, Object>(properties);
}
/**
* Obtains the MIDI file type.
* @return the file's type (0, 1, or 2)
*/
public int getType() {
return type;
}
/**
* Obtains the timing division type for the MIDI file.
*
* @return the division type (PPQ or one of the SMPTE types)
*
* @see Sequence#Sequence(float, int)
* @see Sequence#PPQ
* @see Sequence#SMPTE_24
* @see Sequence#SMPTE_25
* @see Sequence#SMPTE_30DROP
* @see Sequence#SMPTE_30
* @see Sequence#getDivisionType()
*/
public float getDivisionType() {
return divisionType;
}
/**
* Obtains the timing resolution for the MIDI file.
* If the division type is PPQ, the resolution is specified in ticks per beat.
* For SMTPE timing, the resolution is specified in ticks per frame.
*
* @return the number of ticks per beat (PPQ) or per frame (SMPTE)
* @see #getDivisionType
* @see Sequence#getResolution()
*/
public int getResolution() {
return resolution;
}
/**
* Obtains the length of the MIDI file, expressed in 8-bit bytes.
* @return the number of bytes in the file, or UNKNOWN_LENGTH if not known
* @see #UNKNOWN_LENGTH
*/
public int getByteLength() {
return byteLength;
}
/**
* Obtains the length of the MIDI file, expressed in microseconds.
* @return the file's duration in microseconds, or UNKNOWN_LENGTH if not known
* @see Sequence#getMicrosecondLength()
* @see #getByteLength
* @see #UNKNOWN_LENGTH
*/
public long getMicrosecondLength() {
return microsecondLength;
}
/**
* Obtain an unmodifiable map of properties.
* The concept of properties is further explained in
* the {@link MidiFileFormat class description}.
*
* @return a <code>Map&lt;String,Object&gt;</code> object containing
* all properties. If no properties are recognized, an empty map is
* returned.
*
* @see #getProperty(String)
* @since 1.5
*/
public Map<String,Object> properties() {
Map<String,Object> ret;
if (properties == null) {
ret = new HashMap<String,Object>(0);
} else {
ret = (Map<String,Object>) (properties.clone());
}
return (Map<String,Object>) Collections.unmodifiableMap(ret);
}
/**
* Obtain the property value specified by the key.
* The concept of properties is further explained in
* the {@link MidiFileFormat class description}.
*
* <p>If the specified property is not defined for a
* particular file format, this method returns
* <code>null</code>.
*
* @param key the key of the desired property
* @return the value of the property with the specified key,
* or <code>null</code> if the property does not exist.
*
* @see #properties()
* @since 1.5
*/
public Object getProperty(String key) {
if (properties == null) {
return null;
}
return properties.get(key);
}
}

View File

@@ -0,0 +1,192 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* <code>MidiMessage</code> is the base class for MIDI messages. They include
* not only the standard MIDI messages that a synthesizer can respond to, but also
* "meta-events" that can be used by sequencer programs. There are meta-events
* for such information as lyrics, copyrights, tempo indications, time and key
* signatures, markers, etc. For more information, see the Standard MIDI Files 1.0
* specification, which is part of the Complete MIDI 1.0 Detailed Specification
* published by the MIDI Manufacturer's Association
* (<a href = http://www.midi.org>http://www.midi.org</a>).
* <p>
* The base <code>MidiMessage</code> class provides access to three types of
* information about a MIDI message:
* <ul>
* <li>The messages's status byte</li>
* <li>The total length of the message in bytes (the status byte plus any data bytes)</li>
* <li>A byte array containing the complete message</li>
* </ul>
*
* <code>MidiMessage</code> includes methods to get, but not set, these values.
* Setting them is a subclass responsibility.
* <p>
* <a name="integersVsBytes"></a>
* The MIDI standard expresses MIDI data in bytes. However, because
* Java<sup>TM</sup> uses signed bytes, the Java Sound API uses integers
* instead of bytes when expressing MIDI data. For example, the
* {@link #getStatus()} method of
* <code>MidiMessage</code> returns MIDI status bytes as integers. If you are
* processing MIDI data that originated outside Java Sound and now
* is encoded as signed bytes, the bytes can
* can be converted to integers using this conversion:
* <center>{@code int i = (int)(byte & 0xFF)}</center>
* <p>
* If you simply need to pass a known MIDI byte value as a method parameter,
* it can be expressed directly as an integer, using (for example) decimal or
* hexadecimal notation. For instance, to pass the "active sensing" status byte
* as the first argument to ShortMessage's
* {@link ShortMessage#setMessage(int) setMessage(int)}
* method, you can express it as 254 or 0xFE.
*
* @see Track
* @see Sequence
* @see Receiver
*
* @author David Rivas
* @author Kara Kytle
*/
public abstract class MidiMessage implements Cloneable {
// Instance variables
/**
* The MIDI message data. The first byte is the status
* byte for the message; subsequent bytes up to the length
* of the message are data bytes for this message.
* @see #getLength
*/
protected byte[] data;
/**
* The number of bytes in the MIDI message, including the
* status byte and any data bytes.
* @see #getLength
*/
protected int length = 0;
/**
* Constructs a new <code>MidiMessage</code>. This protected
* constructor is called by concrete subclasses, which should
* ensure that the data array specifies a complete, valid MIDI
* message.
*
* @param data an array of bytes containing the complete message.
* The message data may be changed using the <code>setMessage</code>
* method.
*
* @see #setMessage
*/
protected MidiMessage(byte[] data) {
this.data = data;
if (data != null) {
this.length = data.length;
}
}
/**
* Sets the data for the MIDI message. This protected
* method is called by concrete subclasses, which should
* ensure that the data array specifies a complete, valid MIDI
* message.
*
* @param data the data bytes in the MIDI message
* @param length the number of bytes in the data byte array
* @throws InvalidMidiDataException if the parameter values do not specify a valid MIDI meta message
*/
protected void setMessage(byte[] data, int length) throws InvalidMidiDataException {
if (length < 0 || (length > 0 && length > data.length)) {
throw new IndexOutOfBoundsException("length out of bounds: "+length);
}
this.length = length;
if (this.data == null || this.data.length < this.length) {
this.data = new byte[this.length];
}
System.arraycopy(data, 0, this.data, 0, length);
}
/**
* Obtains the MIDI message data. The first byte of the returned byte
* array is the status byte of the message. Any subsequent bytes up to
* the length of the message are data bytes. The byte array may have a
* length which is greater than that of the actual message; the total
* length of the message in bytes is reported by the <code>{@link #getLength}</code>
* method.
*
* @return the byte array containing the complete <code>MidiMessage</code> data
*/
public byte[] getMessage() {
byte[] returnedArray = new byte[length];
System.arraycopy(data, 0, returnedArray, 0, length);
return returnedArray;
}
/**
* Obtains the status byte for the MIDI message. The status "byte" is
* represented as an integer; see the
* <a href="#integersVsBytes">discussion</a> in the
* <code>MidiMessage</code> class description.
*
* @return the integer representation of this event's status byte
*/
public int getStatus() {
if (length > 0) {
return (data[0] & 0xFF);
}
return 0;
}
/**
* Obtains the total length of the MIDI message in bytes. A
* MIDI message consists of one status byte and zero or more
* data bytes. The return value ranges from 1 for system real-time messages,
* to 2 or 3 for channel messages, to any value for meta and system
* exclusive messages.
*
* @return the length of the message in bytes
*/
public int getLength() {
return length;
}
/**
* Creates a new object of the same class and with the same contents
* as this object.
* @return a clone of this instance.
*/
public abstract Object clone();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* A <code>MidiUnavailableException</code> is thrown when a requested MIDI
* component cannot be opened or created because it is unavailable. This often
* occurs when a device is in use by another application. More generally, it
* can occur when there is a finite number of a certain kind of resource that can
* be used for some purpose, and all of them are already in use (perhaps all by
* this application). For an example of the latter case, see the
* {@link Transmitter#setReceiver(Receiver) setReceiver} method of
* <code>Transmitter</code>.
*
* @author Kara Kytle
*/
public class MidiUnavailableException extends Exception {
/**
* Constructs a <code>MidiUnavailableException</code> that has
* <code>null</code> as its error detail message.
*/
public MidiUnavailableException() {
super();
}
/**
* Constructs a <code>MidiUnavailableException</code> with the
* specified detail message.
*
* @param message the string to display as an error detail message
*/
public MidiUnavailableException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* A <code>Patch</code> object represents a location, on a MIDI
* synthesizer, into which a single instrument is stored (loaded).
* Every <code>Instrument</code> object has its own <code>Patch</code>
* object that specifies the memory location
* into which that instrument should be loaded. The
* location is specified abstractly by a bank index and a program number (not by
* any scheme that directly refers to a specific address or offset in RAM).
* This is a hierarchical indexing scheme: MIDI provides for up to 16384 banks,
* each of which contains up to 128 program locations. For example, a
* minimal sort of synthesizer might have only one bank of instruments, and
* only 32 instruments (programs) in that bank.
* <p>
* To select what instrument should play the notes on a particular MIDI
* channel, two kinds of MIDI message are used that specify a patch location:
* a bank-select command, and a program-change channel command. The Java Sound
* equivalent is the
* {@link MidiChannel#programChange(int, int) programChange(int, int)}
* method of <code>MidiChannel</code>.
*
* @see Instrument
* @see Instrument#getPatch()
* @see MidiChannel#programChange(int, int)
* @see Synthesizer#loadInstruments(Soundbank, Patch[])
* @see Soundbank
* @see Sequence#getPatchList()
*
* @author Kara Kytle
*/
public class Patch {
/**
* Bank index
*/
private final int bank;
/**
* Program change number
*/
private final int program;
/**
* Constructs a new patch object from the specified bank and program
* numbers.
* @param bank the bank index (in the range from 0 to 16383)
* @param program the program index (in the range from 0 to 127)
*/
public Patch(int bank, int program) {
this.bank = bank;
this.program = program;
}
/**
* Returns the number of the bank that contains the instrument
* whose location this <code>Patch</code> specifies.
* @return the bank number, whose range is from 0 to 16383
* @see MidiChannel#programChange(int, int)
*/
public int getBank() {
return bank;
}
/**
* Returns the index, within
* a bank, of the instrument whose location this <code>Patch</code> specifies.
* @return the instrument's program number, whose range is from 0 to 127
*
* @see MidiChannel#getProgram
* @see MidiChannel#programChange(int)
* @see MidiChannel#programChange(int, int)
*/
public int getProgram() {
return program;
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* A <code>Receiver</code> receives <code>{@link MidiEvent}</code> objects and
* typically does something useful in response, such as interpreting them to
* generate sound or raw MIDI output. Common MIDI receivers include
* synthesizers and MIDI Out ports.
*
* @see MidiDevice
* @see Synthesizer
* @see Transmitter
*
* @author Kara Kytle
*/
public interface Receiver extends AutoCloseable {
//$$fb 2002-04-12: fix for 4662090: Contradiction in Receiver specification
/**
* Sends a MIDI message and time-stamp to this receiver.
* If time-stamping is not supported by this receiver, the time-stamp
* value should be -1.
* @param message the MIDI message to send
* @param timeStamp the time-stamp for the message, in microseconds.
* @throws IllegalStateException if the receiver is closed
*/
public void send(MidiMessage message, long timeStamp);
/**
* Indicates that the application has finished using the receiver, and
* that limited resources it requires may be released or made available.
*
* <p>If the creation of this <code>Receiver</code> resulted in
* implicitly opening the underlying device, the device is
* implicitly closed by this method. This is true unless the device is
* kept open by other <code>Receiver</code> or <code>Transmitter</code>
* instances that opened the device implicitly, and unless the device
* has been opened explicitly. If the device this
* <code>Receiver</code> is retrieved from is closed explicitly by
* calling {@link MidiDevice#close MidiDevice.close}, the
* <code>Receiver</code> is closed, too. For a detailed
* description of open/close behaviour see the class description
* of {@link javax.sound.midi.MidiDevice MidiDevice}.
*
* @see javax.sound.midi.MidiSystem#getReceiver
*/
public void close();
}

View File

@@ -0,0 +1,336 @@
/*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
import java.util.Vector;
import com.sun.media.sound.MidiUtils;
/**
* A <code>Sequence</code> is a data structure containing musical
* information (often an entire song or composition) that can be played
* back by a <code>{@link Sequencer}</code> object. Specifically, the
* <code>Sequence</code> contains timing
* information and one or more tracks. Each <code>{@link Track track}</code> consists of a
* series of MIDI events (such as note-ons, note-offs, program changes, and meta-events).
* The sequence's timing information specifies the type of unit that is used
* to time-stamp the events in the sequence.
* <p>
* A <code>Sequence</code> can be created from a MIDI file by reading the file
* into an input stream and invoking one of the <code>getSequence</code> methods of
* {@link MidiSystem}. A sequence can also be built from scratch by adding new
* <code>Tracks</code> to an empty <code>Sequence</code>, and adding
* <code>{@link MidiEvent}</code> objects to these <code>Tracks</code>.
*
* @see Sequencer#setSequence(java.io.InputStream stream)
* @see Sequencer#setSequence(Sequence sequence)
* @see Track#add(MidiEvent)
* @see MidiFileFormat
*
* @author Kara Kytle
*/
public class Sequence {
// Timing types
/**
* The tempo-based timing type, for which the resolution is expressed in pulses (ticks) per quarter note.
* @see #Sequence(float, int)
*/
public static final float PPQ = 0.0f;
/**
* The SMPTE-based timing type with 24 frames per second (resolution is expressed in ticks per frame).
* @see #Sequence(float, int)
*/
public static final float SMPTE_24 = 24.0f;
/**
* The SMPTE-based timing type with 25 frames per second (resolution is expressed in ticks per frame).
* @see #Sequence(float, int)
*/
public static final float SMPTE_25 = 25.0f;
/**
* The SMPTE-based timing type with 29.97 frames per second (resolution is expressed in ticks per frame).
* @see #Sequence(float, int)
*/
public static final float SMPTE_30DROP = 29.97f;
/**
* The SMPTE-based timing type with 30 frames per second (resolution is expressed in ticks per frame).
* @see #Sequence(float, int)
*/
public static final float SMPTE_30 = 30.0f;
// Variables
/**
* The timing division type of the sequence.
* @see #PPQ
* @see #SMPTE_24
* @see #SMPTE_25
* @see #SMPTE_30DROP
* @see #SMPTE_30
* @see #getDivisionType
*/
protected float divisionType;
/**
* The timing resolution of the sequence.
* @see #getResolution
*/
protected int resolution;
/**
* The MIDI tracks in this sequence.
* @see #getTracks
*/
protected Vector<Track> tracks = new Vector<Track>();
/**
* Constructs a new MIDI sequence with the specified timing division
* type and timing resolution. The division type must be one of the
* recognized MIDI timing types. For tempo-based timing,
* <code>divisionType</code> is PPQ (pulses per quarter note) and
* the resolution is specified in ticks per beat. For SMTPE timing,
* <code>divisionType</code> specifies the number of frames per
* second and the resolution is specified in ticks per frame.
* The sequence will contain no initial tracks. Tracks may be
* added to or removed from the sequence using <code>{@link #createTrack}</code>
* and <code>{@link #deleteTrack}</code>.
*
* @param divisionType the timing division type (PPQ or one of the SMPTE types)
* @param resolution the timing resolution
* @throws InvalidMidiDataException if <code>divisionType</code> is not valid
*
* @see #PPQ
* @see #SMPTE_24
* @see #SMPTE_25
* @see #SMPTE_30DROP
* @see #SMPTE_30
* @see #getDivisionType
* @see #getResolution
* @see #getTracks
*/
public Sequence(float divisionType, int resolution) throws InvalidMidiDataException {
if (divisionType == PPQ)
this.divisionType = PPQ;
else if (divisionType == SMPTE_24)
this.divisionType = SMPTE_24;
else if (divisionType == SMPTE_25)
this.divisionType = SMPTE_25;
else if (divisionType == SMPTE_30DROP)
this.divisionType = SMPTE_30DROP;
else if (divisionType == SMPTE_30)
this.divisionType = SMPTE_30;
else throw new InvalidMidiDataException("Unsupported division type: " + divisionType);
this.resolution = resolution;
}
/**
* Constructs a new MIDI sequence with the specified timing division
* type, timing resolution, and number of tracks. The division type must be one of the
* recognized MIDI timing types. For tempo-based timing,
* <code>divisionType</code> is PPQ (pulses per quarter note) and
* the resolution is specified in ticks per beat. For SMTPE timing,
* <code>divisionType</code> specifies the number of frames per
* second and the resolution is specified in ticks per frame.
* The sequence will be initialized with the number of tracks specified by
* <code>numTracks</code>. These tracks are initially empty (i.e.
* they contain only the meta-event End of Track).
* The tracks may be retrieved for editing using the <code>{@link #getTracks}</code>
* method. Additional tracks may be added, or existing tracks removed,
* using <code>{@link #createTrack}</code> and <code>{@link #deleteTrack}</code>.
*
* @param divisionType the timing division type (PPQ or one of the SMPTE types)
* @param resolution the timing resolution
* @param numTracks the initial number of tracks in the sequence.
* @throws InvalidMidiDataException if <code>divisionType</code> is not valid
*
* @see #PPQ
* @see #SMPTE_24
* @see #SMPTE_25
* @see #SMPTE_30DROP
* @see #SMPTE_30
* @see #getDivisionType
* @see #getResolution
*/
public Sequence(float divisionType, int resolution, int numTracks) throws InvalidMidiDataException {
if (divisionType == PPQ)
this.divisionType = PPQ;
else if (divisionType == SMPTE_24)
this.divisionType = SMPTE_24;
else if (divisionType == SMPTE_25)
this.divisionType = SMPTE_25;
else if (divisionType == SMPTE_30DROP)
this.divisionType = SMPTE_30DROP;
else if (divisionType == SMPTE_30)
this.divisionType = SMPTE_30;
else throw new InvalidMidiDataException("Unsupported division type: " + divisionType);
this.resolution = resolution;
for (int i = 0; i < numTracks; i++) {
tracks.addElement(new Track());
}
}
/**
* Obtains the timing division type for this sequence.
* @return the division type (PPQ or one of the SMPTE types)
*
* @see #PPQ
* @see #SMPTE_24
* @see #SMPTE_25
* @see #SMPTE_30DROP
* @see #SMPTE_30
* @see #Sequence(float, int)
* @see MidiFileFormat#getDivisionType()
*/
public float getDivisionType() {
return divisionType;
}
/**
* Obtains the timing resolution for this sequence.
* If the sequence's division type is PPQ, the resolution is specified in ticks per beat.
* For SMTPE timing, the resolution is specified in ticks per frame.
*
* @return the number of ticks per beat (PPQ) or per frame (SMPTE)
* @see #getDivisionType
* @see #Sequence(float, int)
* @see MidiFileFormat#getResolution()
*/
public int getResolution() {
return resolution;
}
/**
* Creates a new, initially empty track as part of this sequence.
* The track initially contains the meta-event End of Track.
* The newly created track is returned. All tracks in the sequence
* may be retrieved using <code>{@link #getTracks}</code>. Tracks may be
* removed from the sequence using <code>{@link #deleteTrack}</code>.
* @return the newly created track
*/
public Track createTrack() {
Track track = new Track();
tracks.addElement(track);
return track;
}
/**
* Removes the specified track from the sequence.
* @param track the track to remove
* @return <code>true</code> if the track existed in the track and was removed,
* otherwise <code>false</code>.
*
* @see #createTrack
* @see #getTracks
*/
public boolean deleteTrack(Track track) {
return tracks.removeElement(track);
}
/**
* Obtains an array containing all the tracks in this sequence.
* If the sequence contains no tracks, an array of length 0 is returned.
* @return the array of tracks
*
* @see #createTrack
* @see #deleteTrack
*/
public Track[] getTracks() {
// Creation of the non-empty array will be synchronized inside toArray()
return tracks.toArray(new Track[0]);
}
/**
* Obtains the duration of this sequence, expressed in microseconds.
* @return this sequence's duration in microseconds.
*/
public long getMicrosecondLength() {
return com.sun.media.sound.MidiUtils.tick2microsecond(this, getTickLength(), null);
}
/**
* Obtains the duration of this sequence, expressed in MIDI ticks.
*
* @return this sequence's length in ticks
*
* @see #getMicrosecondLength
*/
public long getTickLength() {
long length = 0;
synchronized(tracks) {
for(int i=0; i<tracks.size(); i++ ) {
long temp = ((Track)tracks.elementAt(i)).ticks();
if( temp>length ) {
length = temp;
}
}
return length;
}
}
/**
* Obtains a list of patches referenced in this sequence.
* This patch list may be used to load the required
* <code>{@link Instrument}</code> objects
* into a <code>{@link Synthesizer}</code>.
*
* @return an array of <code>{@link Patch}</code> objects used in this sequence
*
* @see Synthesizer#loadInstruments(Soundbank, Patch[])
*/
public Patch[] getPatchList() {
// $$kk: 04.09.99: need to implement!!
return new Patch[0];
}
}

View File

@@ -0,0 +1,868 @@
/*
* Copyright (c) 1999, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
import java.io.InputStream;
import java.io.IOException;
/**
* A hardware or software device that plays back a MIDI
* <code>{@link Sequence sequence}</code> is known as a <em>sequencer</em>.
* A MIDI sequence contains lists of time-stamped MIDI data, such as
* might be read from a standard MIDI file. Most
* sequencers also provide functions for creating and editing sequences.
* <p>
* The <code>Sequencer</code> interface includes methods for the following
* basic MIDI sequencer operations:
* <ul>
* <li>obtaining a sequence from MIDI file data</li>
* <li>starting and stopping playback</li>
* <li>moving to an arbitrary position in the sequence</li>
* <li>changing the tempo (speed) of playback</li>
* <li>synchronizing playback to an internal clock or to received MIDI
* messages</li>
* <li>controlling the timing of another device</li>
* </ul>
* In addition, the following operations are supported, either directly, or
* indirectly through objects that the <code>Sequencer</code> has access to:
* <ul>
* <li>editing the data by adding or deleting individual MIDI events or entire
* tracks</li>
* <li>muting or soloing individual tracks in the sequence</li>
* <li>notifying listener objects about any meta-events or
* control-change events encountered while playing back the sequence.</li>
* </ul>
*
* @see Sequencer.SyncMode
* @see #addMetaEventListener
* @see ControllerEventListener
* @see Receiver
* @see Transmitter
* @see MidiDevice
*
* @author Kara Kytle
* @author Florian Bomers
*/
public interface Sequencer extends MidiDevice {
/**
* A value indicating that looping should continue
* indefinitely rather than complete after a specific
* number of loops.
*
* @see #setLoopCount
* @since 1.5
*/
public static final int LOOP_CONTINUOUSLY = -1;
/**
* Sets the current sequence on which the sequencer operates.
*
* <p>This method can be called even if the
* <code>Sequencer</code> is closed.
*
* @param sequence the sequence to be loaded.
* @throws InvalidMidiDataException if the sequence contains invalid
* MIDI data, or is not supported.
*/
public void setSequence(Sequence sequence) throws InvalidMidiDataException;
/**
* Sets the current sequence on which the sequencer operates.
* The stream must point to MIDI file data.
*
* <p>This method can be called even if the
* <code>Sequencer</code> is closed.
*
* @param stream stream containing MIDI file data.
* @throws IOException if an I/O exception occurs during reading of the stream.
* @throws InvalidMidiDataException if invalid data is encountered
* in the stream, or the stream is not supported.
*/
public void setSequence(InputStream stream) throws IOException, InvalidMidiDataException;
/**
* Obtains the sequence on which the Sequencer is currently operating.
*
* <p>This method can be called even if the
* <code>Sequencer</code> is closed.
*
* @return the current sequence, or <code>null</code> if no sequence is currently set.
*/
public Sequence getSequence();
/**
* Starts playback of the MIDI data in the currently
* loaded sequence.
* Playback will begin from the current position.
* If the playback position reaches the loop end point,
* and the loop count is greater than 0, playback will
* resume at the loop start point for the number of
* repetitions set with <code>setLoopCount</code>.
* After that, or if the loop count is 0, playback will
* continue to play to the end of the sequence.
*
* <p>The implementation ensures that the synthesizer
* is brought to a consistent state when jumping
* to the loop start point by sending appropriate
* controllers, pitch bend, and program change events.
*
* @throws IllegalStateException if the <code>Sequencer</code> is
* closed.
*
* @see #setLoopStartPoint
* @see #setLoopEndPoint
* @see #setLoopCount
* @see #stop
*/
public void start();
/**
* Stops recording, if active, and playback of the currently loaded sequence,
* if any.
*
* @throws IllegalStateException if the <code>Sequencer</code> is
* closed.
*
* @see #start
* @see #isRunning
*/
public void stop();
/**
* Indicates whether the Sequencer is currently running. The default is <code>false</code>.
* The Sequencer starts running when either <code>{@link #start}</code> or <code>{@link #startRecording}</code>
* is called. <code>isRunning</code> then returns <code>true</code> until playback of the
* sequence completes or <code>{@link #stop}</code> is called.
* @return <code>true</code> if the Sequencer is running, otherwise <code>false</code>
*/
public boolean isRunning();
/**
* Starts recording and playback of MIDI data. Data is recorded to all enabled tracks,
* on the channel(s) for which they were enabled. Recording begins at the current position
* of the sequencer. Any events already in the track are overwritten for the duration
* of the recording session. Events from the currently loaded sequence,
* if any, are delivered to the sequencer's transmitter(s) along with messages
* received during recording.
* <p>
* Note that tracks are not by default enabled for recording. In order to record MIDI data,
* at least one track must be specifically enabled for recording.
*
* @throws IllegalStateException if the <code>Sequencer</code> is
* closed.
*
* @see #startRecording
* @see #recordEnable
* @see #recordDisable
*/
public void startRecording();
/**
* Stops recording, if active. Playback of the current sequence continues.
*
* @throws IllegalStateException if the <code>Sequencer</code> is
* closed.
*
* @see #startRecording
* @see #isRecording
*/
public void stopRecording();
/**
* Indicates whether the Sequencer is currently recording. The default is <code>false</code>.
* The Sequencer begins recording when <code>{@link #startRecording}</code> is called,
* and then returns <code>true</code> until <code>{@link #stop}</code> or <code>{@link #stopRecording}</code>
* is called.
* @return <code>true</code> if the Sequencer is recording, otherwise <code>false</code>
*/
public boolean isRecording();
/**
* Prepares the specified track for recording events received on a particular channel.
* Once enabled, a track will receive events when recording is active.
* @param track the track to which events will be recorded
* @param channel the channel on which events will be received. If -1 is specified
* for the channel value, the track will receive data from all channels.
* @throws IllegalArgumentException thrown if the track is not part of the current
* sequence.
*/
public void recordEnable(Track track, int channel);
/**
* Disables recording to the specified track. Events will no longer be recorded
* into this track.
* @param track the track to disable for recording, or <code>null</code> to disable
* recording for all tracks.
*/
public void recordDisable(Track track);
/**
* Obtains the current tempo, expressed in beats per minute. The
* actual tempo of playback is the product of the returned value
* and the tempo factor.
*
* @return the current tempo in beats per minute
*
* @see #getTempoFactor
* @see #setTempoInBPM(float)
* @see #getTempoInMPQ
*/
public float getTempoInBPM();
/**
* Sets the tempo in beats per minute. The actual tempo of playback
* is the product of the specified value and the tempo factor.
*
* @param bpm desired new tempo in beats per minute
* @see #getTempoFactor
* @see #setTempoInMPQ(float)
* @see #getTempoInBPM
*/
public void setTempoInBPM(float bpm);
/**
* Obtains the current tempo, expressed in microseconds per quarter
* note. The actual tempo of playback is the product of the returned
* value and the tempo factor.
*
* @return the current tempo in microseconds per quarter note
* @see #getTempoFactor
* @see #setTempoInMPQ(float)
* @see #getTempoInBPM
*/
public float getTempoInMPQ();
/**
* Sets the tempo in microseconds per quarter note. The actual tempo
* of playback is the product of the specified value and the tempo
* factor.
*
* @param mpq desired new tempo in microseconds per quarter note.
* @see #getTempoFactor
* @see #setTempoInBPM(float)
* @see #getTempoInMPQ
*/
public void setTempoInMPQ(float mpq);
/**
* Scales the sequencer's actual playback tempo by the factor provided.
* The default is 1.0. A value of 1.0 represents the natural rate (the
* tempo specified in the sequence), 2.0 means twice as fast, etc.
* The tempo factor does not affect the values returned by
* <code>{@link #getTempoInMPQ}</code> and <code>{@link #getTempoInBPM}</code>.
* Those values indicate the tempo prior to scaling.
* <p>
* Note that the tempo factor cannot be adjusted when external
* synchronization is used. In that situation,
* <code>setTempoFactor</code> always sets the tempo factor to 1.0.
*
* @param factor the requested tempo scalar
* @see #getTempoFactor
*/
public void setTempoFactor(float factor);
/**
* Returns the current tempo factor for the sequencer. The default is
* 1.0.
*
* @return tempo factor.
* @see #setTempoFactor(float)
*/
public float getTempoFactor();
/**
* Obtains the length of the current sequence, expressed in MIDI ticks,
* or 0 if no sequence is set.
* @return length of the sequence in ticks
*/
public long getTickLength();
/**
* Obtains the current position in the sequence, expressed in MIDI
* ticks. (The duration of a tick in seconds is determined both by
* the tempo and by the timing resolution stored in the
* <code>{@link Sequence}</code>.)
*
* @return current tick
* @see #setTickPosition
*/
public long getTickPosition();
/**
* Sets the current sequencer position in MIDI ticks
* @param tick the desired tick position
* @see #getTickPosition
*/
public void setTickPosition(long tick);
/**
* Obtains the length of the current sequence, expressed in microseconds,
* or 0 if no sequence is set.
* @return length of the sequence in microseconds.
*/
public long getMicrosecondLength();
/**
* Obtains the current position in the sequence, expressed in
* microseconds.
* @return the current position in microseconds
* @see #setMicrosecondPosition
*/
public long getMicrosecondPosition();
/**
* Sets the current position in the sequence, expressed in microseconds
* @param microseconds desired position in microseconds
* @see #getMicrosecondPosition
*/
public void setMicrosecondPosition(long microseconds);
/**
* Sets the source of timing information used by this sequencer.
* The sequencer synchronizes to the master, which is the internal clock,
* MIDI clock, or MIDI time code, depending on the value of
* <code>sync</code>. The <code>sync</code> argument must be one
* of the supported modes, as returned by
* <code>{@link #getMasterSyncModes}</code>.
*
* @param sync the desired master synchronization mode
*
* @see SyncMode#INTERNAL_CLOCK
* @see SyncMode#MIDI_SYNC
* @see SyncMode#MIDI_TIME_CODE
* @see #getMasterSyncMode
*/
public void setMasterSyncMode(SyncMode sync);
/**
* Obtains the current master synchronization mode for this sequencer.
*
* @return the current master synchronization mode
*
* @see #setMasterSyncMode(Sequencer.SyncMode)
* @see #getMasterSyncModes
*/
public SyncMode getMasterSyncMode();
/**
* Obtains the set of master synchronization modes supported by this
* sequencer.
*
* @return the available master synchronization modes
*
* @see SyncMode#INTERNAL_CLOCK
* @see SyncMode#MIDI_SYNC
* @see SyncMode#MIDI_TIME_CODE
* @see #getMasterSyncMode
* @see #setMasterSyncMode(Sequencer.SyncMode)
*/
public SyncMode[] getMasterSyncModes();
/**
* Sets the slave synchronization mode for the sequencer.
* This indicates the type of timing information sent by the sequencer
* to its receiver. The <code>sync</code> argument must be one
* of the supported modes, as returned by
* <code>{@link #getSlaveSyncModes}</code>.
*
* @param sync the desired slave synchronization mode
*
* @see SyncMode#MIDI_SYNC
* @see SyncMode#MIDI_TIME_CODE
* @see SyncMode#NO_SYNC
* @see #getSlaveSyncModes
*/
public void setSlaveSyncMode(SyncMode sync);
/**
* Obtains the current slave synchronization mode for this sequencer.
*
* @return the current slave synchronization mode
*
* @see #setSlaveSyncMode(Sequencer.SyncMode)
* @see #getSlaveSyncModes
*/
public SyncMode getSlaveSyncMode();
/**
* Obtains the set of slave synchronization modes supported by the sequencer.
*
* @return the available slave synchronization modes
*
* @see SyncMode#MIDI_SYNC
* @see SyncMode#MIDI_TIME_CODE
* @see SyncMode#NO_SYNC
*/
public SyncMode[] getSlaveSyncModes();
/**
* Sets the mute state for a track. This method may fail for a number
* of reasons. For example, the track number specified may not be valid
* for the current sequence, or the sequencer may not support this functionality.
* An application which needs to verify whether this operation succeeded should
* follow this call with a call to <code>{@link #getTrackMute}</code>.
*
* @param track the track number. Tracks in the current sequence are numbered
* from 0 to the number of tracks in the sequence minus 1.
* @param mute the new mute state for the track. <code>true</code> implies the
* track should be muted, <code>false</code> implies the track should be unmuted.
* @see #getSequence
*/
public void setTrackMute(int track, boolean mute);
/**
* Obtains the current mute state for a track. The default mute
* state for all tracks which have not been muted is false. In any
* case where the specified track has not been muted, this method should
* return false. This applies if the sequencer does not support muting
* of tracks, and if the specified track index is not valid.
*
* @param track the track number. Tracks in the current sequence are numbered
* from 0 to the number of tracks in the sequence minus 1.
* @return <code>true</code> if muted, <code>false</code> if not.
*/
public boolean getTrackMute(int track);
/**
* Sets the solo state for a track. If <code>solo</code> is <code>true</code>
* only this track and other solo'd tracks will sound. If <code>solo</code>
* is <code>false</code> then only other solo'd tracks will sound, unless no
* tracks are solo'd in which case all un-muted tracks will sound.
* <p>
* This method may fail for a number
* of reasons. For example, the track number specified may not be valid
* for the current sequence, or the sequencer may not support this functionality.
* An application which needs to verify whether this operation succeeded should
* follow this call with a call to <code>{@link #getTrackSolo}</code>.
*
* @param track the track number. Tracks in the current sequence are numbered
* from 0 to the number of tracks in the sequence minus 1.
* @param solo the new solo state for the track. <code>true</code> implies the
* track should be solo'd, <code>false</code> implies the track should not be solo'd.
* @see #getSequence
*/
public void setTrackSolo(int track, boolean solo);
/**
* Obtains the current solo state for a track. The default mute
* state for all tracks which have not been solo'd is false. In any
* case where the specified track has not been solo'd, this method should
* return false. This applies if the sequencer does not support soloing
* of tracks, and if the specified track index is not valid.
*
* @param track the track number. Tracks in the current sequence are numbered
* from 0 to the number of tracks in the sequence minus 1.
* @return <code>true</code> if solo'd, <code>false</code> if not.
*/
public boolean getTrackSolo(int track);
/**
* Registers a meta-event listener to receive
* notification whenever a meta-event is encountered in the sequence
* and processed by the sequencer. This method can fail if, for
* instance,this class of sequencer does not support meta-event
* notification.
*
* @param listener listener to add
* @return <code>true</code> if the listener was successfully added,
* otherwise <code>false</code>
*
* @see #removeMetaEventListener
* @see MetaEventListener
* @see MetaMessage
*/
public boolean addMetaEventListener(MetaEventListener listener);
/**
* Removes the specified meta-event listener from this sequencer's
* list of registered listeners, if in fact the listener is registered.
*
* @param listener the meta-event listener to remove
* @see #addMetaEventListener
*/
public void removeMetaEventListener(MetaEventListener listener);
/**
* Registers a controller event listener to receive notification
* whenever the sequencer processes a control-change event of the
* requested type or types. The types are specified by the
* <code>controllers</code> argument, which should contain an array of
* MIDI controller numbers. (Each number should be between 0 and 127,
* inclusive. See the MIDI 1.0 Specification for the numbers that
* correspond to various types of controllers.)
* <p>
* The returned array contains the MIDI controller
* numbers for which the listener will now receive events.
* Some sequencers might not support controller event notification, in
* which case the array has a length of 0. Other sequencers might
* support notification for some controllers but not all.
* This method may be invoked repeatedly.
* Each time, the returned array indicates all the controllers
* that the listener will be notified about, not only the controllers
* requested in that particular invocation.
*
* @param listener the controller event listener to add to the list of
* registered listeners
* @param controllers the MIDI controller numbers for which change
* notification is requested
* @return the numbers of all the MIDI controllers whose changes will
* now be reported to the specified listener
*
* @see #removeControllerEventListener
* @see ControllerEventListener
*/
public int[] addControllerEventListener(ControllerEventListener listener, int[] controllers);
/**
* Removes a controller event listener's interest in one or more
* types of controller event. The <code>controllers</code> argument
* is an array of MIDI numbers corresponding to the controllers for
* which the listener should no longer receive change notifications.
* To completely remove this listener from the list of registered
* listeners, pass in <code>null</code> for <code>controllers</code>.
* The returned array contains the MIDI controller
* numbers for which the listener will now receive events. The
* array has a length of 0 if the listener will not receive
* change notifications for any controllers.
*
* @param listener old listener
* @param controllers the MIDI controller numbers for which change
* notification should be cancelled, or <code>null</code> to cancel
* for all controllers
* @return the numbers of all the MIDI controllers whose changes will
* now be reported to the specified listener
*
* @see #addControllerEventListener
*/
public int[] removeControllerEventListener(ControllerEventListener listener, int[] controllers);
/**
* Sets the first MIDI tick that will be
* played in the loop. If the loop count is
* greater than 0, playback will jump to this
* point when reaching the loop end point.
*
* <p>A value of 0 for the starting point means the
* beginning of the loaded sequence. The starting
* point must be lower than or equal to the ending
* point, and it must fall within the size of the
* loaded sequence.
*
* <p>A sequencer's loop start point defaults to
* start of the sequence.
*
* @param tick the loop's starting position,
* in MIDI ticks (zero-based)
* @throws IllegalArgumentException if the requested
* loop start point cannot be set, usually because
* it falls outside the sequence's
* duration or because the start point is
* after the end point
*
* @see #setLoopEndPoint
* @see #setLoopCount
* @see #getLoopStartPoint
* @see #start
* @since 1.5
*/
public void setLoopStartPoint(long tick);
/**
* Obtains the start position of the loop,
* in MIDI ticks.
*
* @return the start position of the loop,
in MIDI ticks (zero-based)
* @see #setLoopStartPoint
* @since 1.5
*/
public long getLoopStartPoint();
/**
* Sets the last MIDI tick that will be played in
* the loop. If the loop count is 0, the loop end
* point has no effect and playback continues to
* play when reaching the loop end point.
*
* <p>A value of -1 for the ending point
* indicates the last tick of the sequence.
* Otherwise, the ending point must be greater
* than or equal to the starting point, and it must
* fall within the size of the loaded sequence.
*
* <p>A sequencer's loop end point defaults to -1,
* meaning the end of the sequence.
*
* @param tick the loop's ending position,
* in MIDI ticks (zero-based), or
* -1 to indicate the final tick
* @throws IllegalArgumentException if the requested
* loop point cannot be set, usually because
* it falls outside the sequence's
* duration or because the ending point is
* before the starting point
*
* @see #setLoopStartPoint
* @see #setLoopCount
* @see #getLoopEndPoint
* @see #start
* @since 1.5
*/
public void setLoopEndPoint(long tick);
/**
* Obtains the end position of the loop,
* in MIDI ticks.
*
* @return the end position of the loop, in MIDI
* ticks (zero-based), or -1 to indicate
* the end of the sequence
* @see #setLoopEndPoint
* @since 1.5
*/
public long getLoopEndPoint();
/**
* Sets the number of repetitions of the loop for
* playback.
* When the playback position reaches the loop end point,
* it will loop back to the loop start point
* <code>count</code> times, after which playback will
* continue to play to the end of the sequence.
* <p>
* If the current position when this method is invoked
* is greater than the loop end point, playback
* continues to the end of the sequence without looping,
* unless the loop end point is changed subsequently.
* <p>
* A <code>count</code> value of 0 disables looping:
* playback will continue at the loop end point, and it
* will not loop back to the loop start point.
* This is a sequencer's default.
*
* <p>If playback is stopped during looping, the
* current loop status is cleared; subsequent start
* requests are not affected by an interrupted loop
* operation.
*
* @param count the number of times playback should
* loop back from the loop's end position
* to the loop's start position, or
* <code>{@link #LOOP_CONTINUOUSLY}</code>
* to indicate that looping should
* continue until interrupted
*
* @throws IllegalArgumentException if <code>count</code> is
* negative and not equal to {@link #LOOP_CONTINUOUSLY}
*
* @see #setLoopStartPoint
* @see #setLoopEndPoint
* @see #getLoopCount
* @see #start
* @since 1.5
*/
public void setLoopCount(int count);
/**
* Obtains the number of repetitions for
* playback.
*
* @return the number of loops after which
* playback plays to the end of the
* sequence
* @see #setLoopCount
* @see #start
* @since 1.5
*/
public int getLoopCount();
/**
* A <code>SyncMode</code> object represents one of the ways in which
* a MIDI sequencer's notion of time can be synchronized with a master
* or slave device.
* If the sequencer is being synchronized to a master, the
* sequencer revises its current time in response to messages from
* the master. If the sequencer has a slave, the sequencer
* similarly sends messages to control the slave's timing.
* <p>
* There are three predefined modes that specify possible masters
* for a sequencer: <code>INTERNAL_CLOCK</code>,
* <code>MIDI_SYNC</code>, and <code>MIDI_TIME_CODE</code>. The
* latter two work if the sequencer receives MIDI messages from
* another device. In these two modes, the sequencer's time gets reset
* based on system real-time timing clock messages or MIDI time code
* (MTC) messages, respectively. These two modes can also be used
* as slave modes, in which case the sequencer sends the corresponding
* types of MIDI messages to its receiver (whether or not the sequencer
* is also receiving them from a master). A fourth mode,
* <code>NO_SYNC</code>, is used to indicate that the sequencer should
* not control its receiver's timing.
*
* @see Sequencer#setMasterSyncMode(Sequencer.SyncMode)
* @see Sequencer#setSlaveSyncMode(Sequencer.SyncMode)
*/
public static class SyncMode {
/**
* Synchronization mode name.
*/
private String name;
/**
* Constructs a synchronization mode.
* @param name name of the synchronization mode
*/
protected SyncMode(String name) {
this.name = name;
}
/**
* Determines whether two objects are equal.
* Returns <code>true</code> if the objects are identical
* @param obj the reference object with which to compare
* @return <code>true</code> if this object is the same as the
* <code>obj</code> argument, <code>false</code> otherwise
*/
public final boolean equals(Object obj) {
return super.equals(obj);
}
/**
* Finalizes the hashcode method.
*/
public final int hashCode() {
return super.hashCode();
}
/**
* Provides this synchronization mode's name as the string
* representation of the mode.
* @return the name of this synchronization mode
*/
public final String toString() {
return name;
}
/**
* A master synchronization mode that makes the sequencer get
* its timing information from its internal clock. This is not
* a legal slave sync mode.
*/
public static final SyncMode INTERNAL_CLOCK = new SyncMode("Internal Clock");
/**
* A master or slave synchronization mode that specifies the
* use of MIDI clock
* messages. If this mode is used as the master sync mode,
* the sequencer gets its timing information from system real-time
* MIDI clock messages. This mode only applies as the master sync
* mode for sequencers that are also MIDI receivers. If this is the
* slave sync mode, the sequencer sends system real-time MIDI clock
* messages to its receiver. MIDI clock messages are sent at a rate
* of 24 per quarter note.
*/
public static final SyncMode MIDI_SYNC = new SyncMode("MIDI Sync");
/**
* A master or slave synchronization mode that specifies the
* use of MIDI Time Code.
* If this mode is used as the master sync mode,
* the sequencer gets its timing information from MIDI Time Code
* messages. This mode only applies as the master sync
* mode to sequencers that are also MIDI receivers. If this
* mode is used as the
* slave sync mode, the sequencer sends MIDI Time Code
* messages to its receiver. (See the MIDI 1.0 Detailed
* Specification for a description of MIDI Time Code.)
*/
public static final SyncMode MIDI_TIME_CODE = new SyncMode("MIDI Time Code");
/**
* A slave synchronization mode indicating that no timing information
* should be sent to the receiver. This is not a legal master sync
* mode.
*/
public static final SyncMode NO_SYNC = new SyncMode("No Timing");
} // class SyncMode
}

View File

@@ -0,0 +1,496 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* A <code>ShortMessage</code> contains a MIDI message that has at most
* two data bytes following its status byte. The types of MIDI message
* that satisfy this criterion are channel voice, channel mode, system common,
* and system real-time--in other words, everything except system exclusive
* and meta-events. The <code>ShortMessage</code> class provides methods
* for getting and setting the contents of the MIDI message.
* <p>
* A number of <code>ShortMessage</code> methods have integer parameters by which
* you specify a MIDI status or data byte. If you know the numeric value, you
* can express it directly. For system common and system real-time messages,
* you can often use the corresponding fields of <code>ShortMessage</code>, such as
* {@link #SYSTEM_RESET SYSTEM_RESET}. For channel messages,
* the upper four bits of the status byte are specified by a command value and
* the lower four bits are specified by a MIDI channel number. To
* convert incoming MIDI data bytes that are in the form of Java's signed bytes,
* you can use the <A HREF="MidiMessage.html#integersVsBytes">conversion code</A>
* given in the <code>{@link MidiMessage}</code> class description.
*
* @see SysexMessage
* @see MetaMessage
*
* @author David Rivas
* @author Kara Kytle
* @author Florian Bomers
*/
public class ShortMessage extends MidiMessage {
// Status byte defines
// System common messages
/**
* Status byte for MIDI Time Code Quarter Frame message (0xF1, or 241).
* @see MidiMessage#getStatus
*/
public static final int MIDI_TIME_CODE = 0xF1; // 241
/**
* Status byte for Song Position Pointer message (0xF2, or 242).
* @see MidiMessage#getStatus
*/
public static final int SONG_POSITION_POINTER = 0xF2; // 242
/**
* Status byte for MIDI Song Select message (0xF3, or 243).
* @see MidiMessage#getStatus
*/
public static final int SONG_SELECT = 0xF3; // 243
/**
* Status byte for Tune Request message (0xF6, or 246).
* @see MidiMessage#getStatus
*/
public static final int TUNE_REQUEST = 0xF6; // 246
/**
* Status byte for End of System Exclusive message (0xF7, or 247).
* @see MidiMessage#getStatus
*/
public static final int END_OF_EXCLUSIVE = 0xF7; // 247
// System real-time messages
/**
* Status byte for Timing Clock message (0xF8, or 248).
* @see MidiMessage#getStatus
*/
public static final int TIMING_CLOCK = 0xF8; // 248
/**
* Status byte for Start message (0xFA, or 250).
* @see MidiMessage#getStatus
*/
public static final int START = 0xFA; // 250
/**
* Status byte for Continue message (0xFB, or 251).
* @see MidiMessage#getStatus
*/
public static final int CONTINUE = 0xFB; // 251
/**
* Status byte for Stop message (0xFC, or 252).
* @see MidiMessage#getStatus
*/
public static final int STOP = 0xFC; //252
/**
* Status byte for Active Sensing message (0xFE, or 254).
* @see MidiMessage#getStatus
*/
public static final int ACTIVE_SENSING = 0xFE; // 254
/**
* Status byte for System Reset message (0xFF, or 255).
* @see MidiMessage#getStatus
*/
public static final int SYSTEM_RESET = 0xFF; // 255
// Channel voice message upper nibble defines
/**
* Command value for Note Off message (0x80, or 128)
*/
public static final int NOTE_OFF = 0x80; // 128
/**
* Command value for Note On message (0x90, or 144)
*/
public static final int NOTE_ON = 0x90; // 144
/**
* Command value for Polyphonic Key Pressure (Aftertouch) message (0xA0, or 160)
*/
public static final int POLY_PRESSURE = 0xA0; // 160
/**
* Command value for Control Change message (0xB0, or 176)
*/
public static final int CONTROL_CHANGE = 0xB0; // 176
/**
* Command value for Program Change message (0xC0, or 192)
*/
public static final int PROGRAM_CHANGE = 0xC0; // 192
/**
* Command value for Channel Pressure (Aftertouch) message (0xD0, or 208)
*/
public static final int CHANNEL_PRESSURE = 0xD0; // 208
/**
* Command value for Pitch Bend message (0xE0, or 224)
*/
public static final int PITCH_BEND = 0xE0; // 224
// Instance variables
/**
* Constructs a new <code>ShortMessage</code>. The
* contents of the new message are guaranteed to specify
* a valid MIDI message. Subsequently, you may set the
* contents of the message using one of the <code>setMessage</code>
* methods.
* @see #setMessage
*/
public ShortMessage() {
this(new byte[3]);
// Default message data: NOTE_ON on Channel 0 with max volume
data[0] = (byte) (NOTE_ON & 0xFF);
data[1] = (byte) 64;
data[2] = (byte) 127;
length = 3;
}
/**
* Constructs a new {@code ShortMessage} which represents a MIDI
* message that takes no data bytes.
* The contents of the message can be changed by using one of
* the {@code setMessage} methods.
*
* @param status the MIDI status byte
* @throws InvalidMidiDataException if {@code status} does not specify
* a valid MIDI status byte for a message that requires no data bytes
* @see #setMessage(int)
* @see #setMessage(int, int, int)
* @see #setMessage(int, int, int, int)
* @see #getStatus()
* @since 1.7
*/
public ShortMessage(int status) throws InvalidMidiDataException {
super(null);
setMessage(status); // can throw InvalidMidiDataException
}
/**
* Constructs a new {@code ShortMessage} which represents a MIDI message
* that takes up to two data bytes. If the message only takes one data byte,
* the second data byte is ignored. If the message does not take
* any data bytes, both data bytes are ignored.
* The contents of the message can be changed by using one of
* the {@code setMessage} methods.
*
* @param status the MIDI status byte
* @param data1 the first data byte
* @param data2 the second data byte
* @throws InvalidMidiDataException if the status byte or all data bytes
* belonging to the message do not specify a valid MIDI message
* @see #setMessage(int)
* @see #setMessage(int, int, int)
* @see #setMessage(int, int, int, int)
* @see #getStatus()
* @see #getData1()
* @see #getData2()
* @since 1.7
*/
public ShortMessage(int status, int data1, int data2)
throws InvalidMidiDataException {
super(null);
setMessage(status, data1, data2); // can throw InvalidMidiDataException
}
/**
* Constructs a new {@code ShortMessage} which represents a channel
* MIDI message that takes up to two data bytes. If the message only takes
* one data byte, the second data byte is ignored. If the message does not
* take any data bytes, both data bytes are ignored.
* The contents of the message can be changed by using one of
* the {@code setMessage} methods.
*
* @param command the MIDI command represented by this message
* @param channel the channel associated with the message
* @param data1 the first data byte
* @param data2 the second data byte
* @throws InvalidMidiDataException if the command value, channel value
* or all data bytes belonging to the message do not specify
* a valid MIDI message
* @see #setMessage(int)
* @see #setMessage(int, int, int)
* @see #setMessage(int, int, int, int)
* @see #getCommand()
* @see #getChannel()
* @see #getData1()
* @see #getData2()
* @since 1.7
*/
public ShortMessage(int command, int channel, int data1, int data2)
throws InvalidMidiDataException {
super(null);
setMessage(command, channel, data1, data2);
}
/**
* Constructs a new <code>ShortMessage</code>.
* @param data an array of bytes containing the complete message.
* The message data may be changed using the <code>setMessage</code>
* method.
* @see #setMessage
*/
// $$fb this should throw an Exception in case of an illegal message!
protected ShortMessage(byte[] data) {
// $$fb this may set an invalid message.
// Can't correct without compromising compatibility
super(data);
}
/**
* Sets the parameters for a MIDI message that takes no data bytes.
* @param status the MIDI status byte
* @throws InvalidMidiDataException if <code>status</code> does not
* specify a valid MIDI status byte for a message that requires no data bytes.
* @see #setMessage(int, int, int)
* @see #setMessage(int, int, int, int)
*/
public void setMessage(int status) throws InvalidMidiDataException {
// check for valid values
int dataLength = getDataLength(status); // can throw InvalidMidiDataException
if (dataLength != 0) {
throw new InvalidMidiDataException("Status byte; " + status + " requires " + dataLength + " data bytes");
}
setMessage(status, 0, 0);
}
/**
* Sets the parameters for a MIDI message that takes one or two data
* bytes. If the message takes only one data byte, the second data
* byte is ignored; if the message does not take any data bytes, both
* data bytes are ignored.
*
* @param status the MIDI status byte
* @param data1 the first data byte
* @param data2 the second data byte
* @throws InvalidMidiDataException if the
* the status byte, or all data bytes belonging to the message, do
* not specify a valid MIDI message.
* @see #setMessage(int, int, int, int)
* @see #setMessage(int)
*/
public void setMessage(int status, int data1, int data2) throws InvalidMidiDataException {
// check for valid values
int dataLength = getDataLength(status); // can throw InvalidMidiDataException
if (dataLength > 0) {
if (data1 < 0 || data1 > 127) {
throw new InvalidMidiDataException("data1 out of range: " + data1);
}
if (dataLength > 1) {
if (data2 < 0 || data2 > 127) {
throw new InvalidMidiDataException("data2 out of range: " + data2);
}
}
}
// set the length
length = dataLength + 1;
// re-allocate array if ShortMessage(byte[]) constructor gave array with fewer elements
if (data == null || data.length < length) {
data = new byte[3];
}
// set the data
data[0] = (byte) (status & 0xFF);
if (length > 1) {
data[1] = (byte) (data1 & 0xFF);
if (length > 2) {
data[2] = (byte) (data2 & 0xFF);
}
}
}
/**
* Sets the short message parameters for a channel message
* which takes up to two data bytes. If the message only
* takes one data byte, the second data byte is ignored; if
* the message does not take any data bytes, both data bytes
* are ignored.
*
* @param command the MIDI command represented by this message
* @param channel the channel associated with the message
* @param data1 the first data byte
* @param data2 the second data byte
* @throws InvalidMidiDataException if the
* status byte or all data bytes belonging to the message, do
* not specify a valid MIDI message
*
* @see #setMessage(int, int, int)
* @see #setMessage(int)
* @see #getCommand
* @see #getChannel
* @see #getData1
* @see #getData2
*/
public void setMessage(int command, int channel, int data1, int data2) throws InvalidMidiDataException {
// check for valid values
if (command >= 0xF0 || command < 0x80) {
throw new InvalidMidiDataException("command out of range: 0x" + Integer.toHexString(command));
}
if ((channel & 0xFFFFFFF0) != 0) { // <=> (channel<0 || channel>15)
throw new InvalidMidiDataException("channel out of range: " + channel);
}
setMessage((command & 0xF0) | (channel & 0x0F), data1, data2);
}
/**
* Obtains the MIDI channel associated with this event. This method
* assumes that the event is a MIDI channel message; if not, the return
* value will not be meaningful.
* @return MIDI channel associated with the message.
* @see #setMessage(int, int, int, int)
*/
public int getChannel() {
// this returns 0 if an invalid message is set
return (getStatus() & 0x0F);
}
/**
* Obtains the MIDI command associated with this event. This method
* assumes that the event is a MIDI channel message; if not, the return
* value will not be meaningful.
* @return the MIDI command associated with this event
* @see #setMessage(int, int, int, int)
*/
public int getCommand() {
// this returns 0 if an invalid message is set
return (getStatus() & 0xF0);
}
/**
* Obtains the first data byte in the message.
* @return the value of the <code>data1</code> field
* @see #setMessage(int, int, int)
*/
public int getData1() {
if (length > 1) {
return (data[1] & 0xFF);
}
return 0;
}
/**
* Obtains the second data byte in the message.
* @return the value of the <code>data2</code> field
* @see #setMessage(int, int, int)
*/
public int getData2() {
if (length > 2) {
return (data[2] & 0xFF);
}
return 0;
}
/**
* Creates a new object of the same class and with the same contents
* as this object.
* @return a clone of this instance.
*/
public Object clone() {
byte[] newData = new byte[length];
System.arraycopy(data, 0, newData, 0, newData.length);
ShortMessage msg = new ShortMessage(newData);
return msg;
}
/**
* Retrieves the number of data bytes associated with a particular
* status byte value.
* @param status status byte value, which must represent a short MIDI message
* @return data length in bytes (0, 1, or 2)
* @throws InvalidMidiDataException if the
* <code>status</code> argument does not represent the status byte for any
* short message
*/
protected final int getDataLength(int status) throws InvalidMidiDataException {
// system common and system real-time messages
switch(status) {
case 0xF6: // Tune Request
case 0xF7: // EOX
// System real-time messages
case 0xF8: // Timing Clock
case 0xF9: // Undefined
case 0xFA: // Start
case 0xFB: // Continue
case 0xFC: // Stop
case 0xFD: // Undefined
case 0xFE: // Active Sensing
case 0xFF: // System Reset
return 0;
case 0xF1: // MTC Quarter Frame
case 0xF3: // Song Select
return 1;
case 0xF2: // Song Position Pointer
return 2;
default:
}
// channel voice and mode messages
switch(status & 0xF0) {
case 0x80:
case 0x90:
case 0xA0:
case 0xB0:
case 0xE0:
return 2;
case 0xC0:
case 0xD0:
return 1;
default:
throw new InvalidMidiDataException("Invalid status byte: " + status);
}
}
}

View File

@@ -0,0 +1,133 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
import java.net.URL;
/**
* A <code>Soundbank</code> contains a set of <code>Instruments</code>
* that can be loaded into a <code>Synthesizer</code>.
* Note that a Java Sound <code>Soundbank</code> is different from a MIDI bank.
* MIDI permits up to 16383 banks, each containing up to 128 instruments
* (also sometimes called programs, patches, or timbres).
* However, a <code>Soundbank</code> can contain 16383 times 128 instruments,
* because the instruments within a <code>Soundbank</code> are indexed by both
* a MIDI program number and a MIDI bank number (via a <code>Patch</code>
* object). Thus, a <code>Soundbank</code> can be thought of as a collection
* of MIDI banks.
* <p>
* <code>Soundbank</code> includes methods that return <code>String</code>
* objects containing the sound bank's name, manufacturer, version number, and
* description. The precise content and format of these strings is left
* to the implementor.
* <p>
* Different synthesizers use a variety of synthesis techniques. A common
* one is wavetable synthesis, in which a segment of recorded sound is
* played back, often with looping and pitch change. The Downloadable Sound
* (DLS) format uses segments of recorded sound, as does the Headspace Engine.
* <code>Soundbanks</code> and <code>Instruments</code> that are based on
* wavetable synthesis (or other uses of stored sound recordings) should
* typically implement the <code>getResources()</code>
* method to provide access to these recorded segments. This is optional,
* however; the method can return an zero-length array if the synthesis technique
* doesn't use sampled sound (FM synthesis and physical modeling are examples
* of such techniques), or if it does but the implementor chooses not to make the
* samples accessible.
*
* @see Synthesizer#getDefaultSoundbank
* @see Synthesizer#isSoundbankSupported
* @see Synthesizer#loadInstruments(Soundbank, Patch[])
* @see Patch
* @see Instrument
* @see SoundbankResource
*
* @author David Rivas
* @author Kara Kytle
*/
public interface Soundbank {
/**
* Obtains the name of the sound bank.
* @return a <code>String</code> naming the sound bank
*/
public String getName();
/**
* Obtains the version string for the sound bank.
* @return a <code>String</code> that indicates the sound bank's version
*/
public String getVersion();
/**
* Obtains a <code>string</code> naming the company that provides the
* sound bank
* @return the vendor string
*/
public String getVendor();
/**
* Obtains a textual description of the sound bank, suitable for display.
* @return a <code>String</code> that describes the sound bank
*/
public String getDescription();
/**
* Extracts a list of non-Instrument resources contained in the sound bank.
* @return an array of resources, excluding instruments. If the sound bank contains
* no resources (other than instruments), returns an array of length 0.
*/
public SoundbankResource[] getResources();
/**
* Obtains a list of instruments contained in this sound bank.
* @return an array of the <code>Instruments</code> in this
* <code>SoundBank</code>
* If the sound bank contains no instruments, returns an array of length 0.
*
* @see Synthesizer#getLoadedInstruments
* @see #getInstrument(Patch)
*/
public Instrument[] getInstruments();
/**
* Obtains an <code>Instrument</code> from the given <code>Patch</code>.
* @param patch a <code>Patch</code> object specifying the bank index
* and program change number
* @return the requested instrument, or <code>null</code> if the
* sound bank doesn't contain that instrument
*
* @see #getInstruments
* @see Synthesizer#loadInstruments(Soundbank, Patch[])
*/
public Instrument getInstrument(Patch patch);
}

View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 1999, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* A <code>SoundbankResource</code> represents any audio resource stored
* in a <code>{@link Soundbank}</code>. Common soundbank resources include:
* <ul>
* <li>Instruments. An instrument may be specified in a variety of
* ways. However, all soundbanks have some mechanism for defining
* instruments. In doing so, they may reference other resources
* stored in the soundbank. Each instrument has a <code>Patch</code>
* which specifies the MIDI program and bank by which it may be
* referenced in MIDI messages. Instrument information may be
* stored in <code>{@link Instrument}</code> objects.
* <li>Audio samples. A sample typically is a sampled audio waveform
* which contains a short sound recording whose duration is a fraction of
* a second, or at most a few seconds. These audio samples may be
* used by a <code>{@link Synthesizer}</code> to synthesize sound in response to MIDI
* commands, or extracted for use by an application.
* (The terminology reflects musicians' use of the word "sample" to refer
* collectively to a series of contiguous audio samples or frames, rather than
* to a single, instantaneous sample.)
* The data class for an audio sample will be an object
* that encapsulates the audio sample data itself and information
* about how to interpret it (the format of the audio data), such
* as an <code>{@link javax.sound.sampled.AudioInputStream}</code>. </li>
* <li>Embedded sequences. A sound bank may contain built-in
* song data stored in a data object such as a <code>{@link Sequence}</code>.
* </ul>
* <p>
* Synthesizers that use wavetable synthesis or related
* techniques play back the audio in a sample when
* synthesizing notes, often when emulating the real-world instrument that
* was originally recorded. However, there is not necessarily a one-to-one
* correspondence between the <code>Instruments</code> and samples
* in a <code>Soundbank</code>. A single <code>Instrument</code> can use
* multiple SoundbankResources (typically for notes of dissimilar pitch or
* brightness). Also, more than one <code>Instrument</code> can use the same
* sample.
*
* @author Kara Kytle
*/
public abstract class SoundbankResource {
/**
* The sound bank that contains the <code>SoundbankResources</code>
*/
private final Soundbank soundBank;
/**
* The name of the <code>SoundbankResource</code>
*/
private final String name;
/**
* The class used to represent the sample's data.
*/
private final Class dataClass;
/**
* The wavetable index.
*/
//private final int index;
/**
* Constructs a new <code>SoundbankResource</code> from the given sound bank
* and wavetable index. (Setting the <code>SoundbankResource's</code> name,
* sampled audio data, and instruments is a subclass responsibility.)
* @param soundBank the sound bank containing this <code>SoundbankResource</code>
* @param name the name of the sample
* @param dataClass the class used to represent the sample's data
*
* @see #getSoundbank
* @see #getName
* @see #getDataClass
* @see #getData
*/
protected SoundbankResource(Soundbank soundBank, String name, Class<?> dataClass) {
this.soundBank = soundBank;
this.name = name;
this.dataClass = dataClass;
}
/**
* Obtains the sound bank that contains this <code>SoundbankResource</code>.
* @return the sound bank in which this <code>SoundbankResource</code> is stored
*/
public Soundbank getSoundbank() {
return soundBank;
}
/**
* Obtains the name of the resource. This should generally be a string
* descriptive of the resource.
* @return the instrument's name
*/
public String getName() {
return name;
}
/**
* Obtains the class used by this sample to represent its data.
* The object returned by <code>getData</code> will be of this
* class. If this <code>SoundbankResource</code> object does not support
* direct access to its data, returns <code>null</code>.
* @return the class used to represent the sample's data, or
* null if the data is not accessible
*/
public Class<?> getDataClass() {
return dataClass;
}
/**
* Obtains the sampled audio that is stored in this <code>SoundbankResource</code>.
* The type of object returned depends on the implementation of the
* concrete class, and may be queried using <code>getDataClass</code>.
* @return an object containing the sampled audio data
* @see #getDataClass
*/
public abstract Object getData();
/**
* Obtains the index of this <code>SoundbankResource</code> into the
* <code>Soundbank's</code> set of <code>SoundbankResources</code>.
* @return the wavetable index
*/
//public int getIndex() {
// return index;
//}
/**
* Obtains a list of the instruments in the sound bank that use the
* <code>SoundbankResource</code> for sound synthesis.
* @return an array of <code>Instruments</code> that reference this
* <code>SoundbankResource</code>
*
* @see Instrument#getSamples
*/
//public abstract Instrument[] getInstruments();
}

View File

@@ -0,0 +1,394 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
import javax.sound.sampled.Control;
/**
* A <code>Synthesizer</code> generates sound. This usually happens when one of
* the <code>Synthesizer</code>'s {@link MidiChannel} objects receives a
* {@link MidiChannel#noteOn(int, int) noteOn} message, either
* directly or via the <code>Synthesizer</code> object.
* Many <code>Synthesizer</code>s support <code>Receivers</code>, through which
* MIDI events can be delivered to the <code>Synthesizer</code>.
* In such cases, the <code>Synthesizer</code> typically responds by sending
* a corresponding message to the appropriate <code>MidiChannel</code>, or by
* processing the event itself if the event isn't one of the MIDI channel
* messages.
* <p>
* The <code>Synthesizer</code> interface includes methods for loading and
* unloading instruments from soundbanks. An instrument is a specification for synthesizing a
* certain type of sound, whether that sound emulates a traditional instrument or is
* some kind of sound effect or other imaginary sound. A soundbank is a collection of instruments, organized
* by bank and program number (via the instrument's <code>Patch</code> object).
* Different <code>Synthesizer</code> classes might implement different sound-synthesis
* techniques, meaning that some instruments and not others might be compatible with a
* given synthesizer.
* Also, synthesizers may have a limited amount of memory for instruments, meaning
* that not every soundbank and instrument can be used by every synthesizer, even if
* the synthesis technique is compatible.
* To see whether the instruments from
* a certain soundbank can be played by a given synthesizer, invoke the
* {@link #isSoundbankSupported(Soundbank) isSoundbankSupported} method of
* <code>Synthesizer</code>.
* <p>
* "Loading" an instrument means that that instrument becomes available for
* synthesizing notes. The instrument is loaded into the bank and
* program location specified by its <code>Patch</code> object. Loading does
* not necessarily mean that subsequently played notes will immediately have
* the sound of this newly loaded instrument. For the instrument to play notes,
* one of the synthesizer's <code>MidiChannel</code> objects must receive (or have received)
* a program-change message that causes that particular instrument's
* bank and program number to be selected.
*
* @see MidiSystem#getSynthesizer
* @see Soundbank
* @see Instrument
* @see MidiChannel#programChange(int, int)
* @see Receiver
* @see Transmitter
* @see MidiDevice
*
* @author Kara Kytle
*/
public interface Synthesizer extends MidiDevice {
// SYNTHESIZER METHODS
/**
* Obtains the maximum number of notes that this synthesizer can sound simultaneously.
* @return the maximum number of simultaneous notes
* @see #getVoiceStatus
*/
public int getMaxPolyphony();
/**
* Obtains the processing latency incurred by this synthesizer, expressed in
* microseconds. This latency measures the worst-case delay between the
* time a MIDI message is delivered to the synthesizer and the time that the
* synthesizer actually produces the corresponding result.
* <p>
* Although the latency is expressed in microseconds, a synthesizer's actual measured
* delay may vary over a wider range than this resolution suggests. For example,
* a synthesizer might have a worst-case delay of a few milliseconds or more.
*
* @return the worst-case delay, in microseconds
*/
public long getLatency();
/**
* Obtains the set of MIDI channels controlled by this synthesizer. Each
* non-null element in the returned array is a <code>MidiChannel</code> that
* receives the MIDI messages sent on that channel number.
* <p>
* The MIDI 1.0 specification provides for 16 channels, so this
* method returns an array of at least 16 elements. However, if this synthesizer
* doesn't make use of all 16 channels, some of the elements of the array
* might be <code>null</code>, so you should check each element
* before using it.
* @return an array of the <code>MidiChannel</code> objects managed by this
* <code>Synthesizer</code>. Some of the array elements may be <code>null</code>.
*/
public MidiChannel[] getChannels();
/**
* Obtains the current status of the voices produced by this synthesizer.
* If this class of <code>Synthesizer</code> does not provide voice
* information, the returned array will always be of length 0. Otherwise,
* its length is always equal to the total number of voices, as returned by
* <code>getMaxPolyphony()</code>. (See the <code>VoiceStatus</code> class
* description for an explanation of synthesizer voices.)
*
* @return an array of <code>VoiceStatus</code> objects that supply
* information about the corresponding synthesizer voices
* @see #getMaxPolyphony
* @see VoiceStatus
*/
public VoiceStatus[] getVoiceStatus();
/**
* Informs the caller whether this synthesizer is capable of loading
* instruments from the specified soundbank.
* If the soundbank is unsupported, any attempts to load instruments from
* it will result in an <code>IllegalArgumentException</code>.
* @param soundbank soundbank for which support is queried
* @return <code>true</code> if the soundbank is supported, otherwise <code>false</code>
* @see #loadInstruments
* @see #loadAllInstruments
* @see #unloadInstruments
* @see #unloadAllInstruments
* @see #getDefaultSoundbank
*/
public boolean isSoundbankSupported(Soundbank soundbank);
/**
* Makes a particular instrument available for synthesis. This instrument
* is loaded into the patch location specified by its <code>Patch</code>
* object, so that if a program-change message is
* received (or has been received) that causes that patch to be selected,
* subsequent notes will be played using the sound of
* <code>instrument</code>. If the specified instrument is already loaded,
* this method does nothing and returns <code>true</code>.
* <p>
* The instrument must be part of a soundbank
* that this <code>Synthesizer</code> supports. (To make sure, you can use
* the <code>getSoundbank</code> method of <code>Instrument</code> and the
* <code>isSoundbankSupported</code> method of <code>Synthesizer</code>.)
* @param instrument instrument to load
* @return <code>true</code> if the instrument is successfully loaded (or
* already had been), <code>false</code> if the instrument could not be
* loaded (for example, if the synthesizer has insufficient
* memory to load it)
* @throws IllegalArgumentException if this
* <code>Synthesizer</code> doesn't support the specified instrument's
* soundbank
* @see #unloadInstrument
* @see #loadInstruments
* @see #loadAllInstruments
* @see #remapInstrument
* @see SoundbankResource#getSoundbank
* @see MidiChannel#programChange(int, int)
*/
public boolean loadInstrument(Instrument instrument);
/**
* Unloads a particular instrument.
* @param instrument instrument to unload
* @throws IllegalArgumentException if this
* <code>Synthesizer</code> doesn't support the specified instrument's
* soundbank
* @see #loadInstrument
* @see #unloadInstruments
* @see #unloadAllInstruments
* @see #getLoadedInstruments
* @see #remapInstrument
*/
public void unloadInstrument(Instrument instrument);
/**
* Remaps an instrument. Instrument <code>to</code> takes the
* place of instrument <code>from</code>.<br>
* For example, if <code>from</code> was located at bank number 2,
* program number 11, remapping causes that bank and program location
* to be occupied instead by <code>to</code>.<br>
* If the function succeeds, instrument <code>from</code> is unloaded.
* <p>To cancel the remapping reload instrument <code>from</code> by
* invoking one of {@link #loadInstrument}, {@link #loadInstruments}
* or {@link #loadAllInstruments}.
*
* @param from the <code>Instrument</code> object to be replaced
* @param to the <code>Instrument</code> object to be used in place
* of the old instrument, it should be loaded into the synthesizer
* @return <code>true</code> if the instrument successfully remapped,
* <code>false</code> if feature is not implemented by synthesizer
* @throws IllegalArgumentException if instrument
* <code>from</code> or instrument <code>to</code> aren't supported by
* synthesizer or if instrument <code>to</code> is not loaded
* @throws NullPointerException if <code>from</code> or
* <code>to</code> parameters have null value
* @see #loadInstrument
* @see #loadInstruments
* @see #loadAllInstruments
*/
public boolean remapInstrument(Instrument from, Instrument to);
/**
* Obtains the default soundbank for the synthesizer, if one exists.
* (Some synthesizers provide a default or built-in soundbank.)
* If a synthesizer doesn't have a default soundbank, instruments must
* be loaded explicitly from an external soundbank.
* @return default soundbank, or <code>null</code> if one does not exist.
* @see #isSoundbankSupported
*/
public Soundbank getDefaultSoundbank();
/**
* Obtains a list of instruments that come with the synthesizer. These
* instruments might be built into the synthesizer, or they might be
* part of a default soundbank provided with the synthesizer, etc.
* <p>
* Note that you don't use this method to find out which instruments are
* currently loaded onto the synthesizer; for that purpose, you use
* <code>getLoadedInstruments()</code>.
* Nor does the method indicate all the instruments that can be loaded onto
* the synthesizer; it only indicates the subset that come with the synthesizer.
* To learn whether another instrument can be loaded, you can invoke
* <code>isSoundbankSupported()</code>, and if the instrument's
* <code>Soundbank</code> is supported, you can try loading the instrument.
*
* @return list of available instruments. If the synthesizer
* has no instruments coming with it, an array of length 0 is returned.
* @see #getLoadedInstruments
* @see #isSoundbankSupported(Soundbank)
* @see #loadInstrument
*/
public Instrument[] getAvailableInstruments();
/**
* Obtains a list of the instruments that are currently loaded onto this
* <code>Synthesizer</code>.
* @return a list of currently loaded instruments
* @see #loadInstrument
* @see #getAvailableInstruments
* @see Soundbank#getInstruments
*/
public Instrument[] getLoadedInstruments();
/**
* Loads onto the <code>Synthesizer</code> all instruments contained
* in the specified <code>Soundbank</code>.
* @param soundbank the <code>Soundbank</code> whose are instruments are
* to be loaded
* @return <code>true</code> if the instruments are all successfully loaded (or
* already had been), <code>false</code> if any instrument could not be
* loaded (for example, if the <code>Synthesizer</code> had insufficient memory)
* @throws IllegalArgumentException if the requested soundbank is
* incompatible with this synthesizer.
* @see #isSoundbankSupported
* @see #loadInstrument
* @see #loadInstruments
*/
public boolean loadAllInstruments(Soundbank soundbank);
/**
* Unloads all instruments contained in the specified <code>Soundbank</code>.
* @param soundbank soundbank containing instruments to unload
* @throws IllegalArgumentException thrown if the soundbank is not supported.
* @see #isSoundbankSupported
* @see #unloadInstrument
* @see #unloadInstruments
*/
public void unloadAllInstruments(Soundbank soundbank);
/**
* Loads the instruments referenced by the specified patches, from the
* specified <code>Soundbank</code>. Each of the <code>Patch</code> objects
* indicates a bank and program number; the <code>Instrument</code> that
* has the matching <code>Patch</code> is loaded into that bank and program
* location.
* @param soundbank the <code>Soundbank</code> containing the instruments to load
* @param patchList list of patches for which instruments should be loaded
* @return <code>true</code> if the instruments are all successfully loaded (or
* already had been), <code>false</code> if any instrument could not be
* loaded (for example, if the <code>Synthesizer</code> had insufficient memory)
* @throws IllegalArgumentException thrown if the soundbank is not supported.
* @see #isSoundbankSupported
* @see Instrument#getPatch
* @see #loadAllInstruments
* @see #loadInstrument
* @see Soundbank#getInstrument(Patch)
* @see Sequence#getPatchList()
*/
public boolean loadInstruments(Soundbank soundbank, Patch[] patchList);
/**
* Unloads the instruments referenced by the specified patches, from the MIDI sound bank specified.
* @param soundbank soundbank containing instruments to unload
* @param patchList list of patches for which instruments should be unloaded
* @throws IllegalArgumentException thrown if the soundbank is not supported.
*
* @see #unloadInstrument
* @see #unloadAllInstruments
* @see #isSoundbankSupported
* @see Instrument#getPatch
* @see #loadInstruments
*/
public void unloadInstruments(Soundbank soundbank, Patch[] patchList);
// RECEIVER METHODS
/**
* Obtains the name of the receiver.
* @return receiver name
*/
// public abstract String getName();
/**
* Opens the receiver.
* @throws MidiUnavailableException if the receiver is cannot be opened,
* usually because the MIDI device is in use by another application.
* @throws SecurityException if the receiver cannot be opened due to security
* restrictions.
*/
// public abstract void open() throws MidiUnavailableException, SecurityException;
/**
* Closes the receiver.
*/
// public abstract void close();
/**
* Sends a MIDI event to the receiver.
* @param event event to send.
* @throws IllegalStateException if the receiver is not open.
*/
// public void send(MidiEvent event) throws IllegalStateException {
//
// }
/**
* Obtains the set of controls supported by the
* element. If no controls are supported, returns an
* array of length 0.
* @return set of controls
*/
// $$kk: 03.04.99: josh bloch recommends getting rid of this:
// what can you really do with a set of untyped controls??
// $$kk: 03.05.99: i am putting this back in. for one thing,
// you can check the length and know whether you should keep
// looking....
// public Control[] getControls();
/**
* Obtains the specified control.
* @param controlClass class of the requested control
* @return requested control object, or null if the
* control is not supported.
*/
// public Control getControl(Class controlClass);
}

View File

@@ -0,0 +1,252 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* A <code>SysexMessage</code> object represents a MIDI system exclusive message.
* <p>
* When a system exclusive message is read from a MIDI file, it always has
* a defined length. Data from a system exclusive message from a MIDI file
* should be stored in the data array of a <code>SysexMessage</code> as
* follows: the system exclusive message status byte (0xF0 or 0xF7), all
* message data bytes, and finally the end-of-exclusive flag (0xF7).
* The length reported by the <code>SysexMessage</code> object is therefore
* the length of the system exclusive data plus two: one byte for the status
* byte and one for the end-of-exclusive flag.
* <p>
* As dictated by the Standard MIDI Files specification, two status byte values are legal
* for a <code>SysexMessage</code> read from a MIDI file:
* <ul>
* <li>0xF0: System Exclusive message (same as in MIDI wire protocol)</li>
* <li>0xF7: Special System Exclusive message</li>
* </ul>
* <p>
* When Java Sound is used to handle system exclusive data that is being received
* using MIDI wire protocol, it should place the data in one or more
* <code>SysexMessages</code>. In this case, the length of the system exclusive data
* is not known in advance; the end of the system exclusive data is marked by an
* end-of-exclusive flag (0xF7) in the MIDI wire byte stream.
* <ul>
* <li>0xF0: System Exclusive message (same as in MIDI wire protocol)</li>
* <li>0xF7: End of Exclusive (EOX)</li>
* </ul>
* The first <code>SysexMessage</code> object containing data for a particular system
* exclusive message should have the status value 0xF0. If this message contains all
* the system exclusive data
* for the message, it should end with the status byte 0xF7 (EOX).
* Otherwise, additional system exclusive data should be sent in one or more
* <code>SysexMessages</code> with a status value of 0xF7. The <code>SysexMessage</code>
* containing the last of the data for the system exclusive message should end with the
* value 0xF7 (EOX) to mark the end of the system exclusive message.
* <p>
* If system exclusive data from <code>SysexMessages</code> objects is being transmitted
* using MIDI wire protocol, only the initial 0xF0 status byte, the system exclusive
* data itself, and the final 0xF7 (EOX) byte should be propagated; any 0xF7 status
* bytes used to indicate that a <code>SysexMessage</code> contains continuing system
* exclusive data should not be propagated via MIDI wire protocol.
*
* @author David Rivas
* @author Kara Kytle
* @author Florian Bomers
*/
public class SysexMessage extends MidiMessage {
// Status byte defines
/**
* Status byte for System Exclusive message (0xF0, or 240).
* @see MidiMessage#getStatus
*/
public static final int SYSTEM_EXCLUSIVE = 0xF0; // 240
/**
* Status byte for Special System Exclusive message (0xF7, or 247), which is used
* in MIDI files. It has the same value as END_OF_EXCLUSIVE, which
* is used in the real-time "MIDI wire" protocol.
* @see MidiMessage#getStatus
*/
public static final int SPECIAL_SYSTEM_EXCLUSIVE = 0xF7; // 247
// Instance variables
/*
* The data bytes for this system exclusive message. These are
* initialized to <code>null</code> and are set explicitly
* by {@link #setMessage(int, byte[], int, long) setMessage}.
*/
//protected byte[] data = null;
/**
* Constructs a new <code>SysexMessage</code>. The
* contents of the new message are guaranteed to specify
* a valid MIDI message. Subsequently, you may set the
* contents of the message using one of the <code>setMessage</code>
* methods.
* @see #setMessage
*/
public SysexMessage() {
this(new byte[2]);
// Default sysex message data: SOX followed by EOX
data[0] = (byte) (SYSTEM_EXCLUSIVE & 0xFF);
data[1] = (byte) (ShortMessage.END_OF_EXCLUSIVE & 0xFF);
}
/**
* Constructs a new {@code SysexMessage} and sets the data for
* the message. The first byte of the data array must be a valid system
* exclusive status byte (0xF0 or 0xF7).
* The contents of the message can be changed by using one of
* the {@code setMessage} methods.
*
* @param data the system exclusive message data including the status byte
* @param length the length of the valid message data in the array,
* including the status byte; it should be non-negative and less than
* or equal to {@code data.length}
* @throws InvalidMidiDataException if the parameter values
* do not specify a valid MIDI meta message.
* @see #setMessage(byte[], int)
* @see #setMessage(int, byte[], int)
* @see #getData()
* @since 1.7
*/
public SysexMessage(byte[] data, int length)
throws InvalidMidiDataException {
super(null);
setMessage(data, length);
}
/**
* Constructs a new {@code SysexMessage} and sets the data for the message.
* The contents of the message can be changed by using one of
* the {@code setMessage} methods.
*
* @param status the status byte for the message; it must be a valid system
* exclusive status byte (0xF0 or 0xF7)
* @param data the system exclusive message data (without the status byte)
* @param length the length of the valid message data in the array;
* it should be non-negative and less than or equal to
* {@code data.length}
* @throws InvalidMidiDataException if the parameter values
* do not specify a valid MIDI meta message.
* @see #setMessage(byte[], int)
* @see #setMessage(int, byte[], int)
* @see #getData()
* @since 1.7
*/
public SysexMessage(int status, byte[] data, int length)
throws InvalidMidiDataException {
super(null);
setMessage(status, data, length);
}
/**
* Constructs a new <code>SysexMessage</code>.
* @param data an array of bytes containing the complete message.
* The message data may be changed using the <code>setMessage</code>
* method.
* @see #setMessage
*/
protected SysexMessage(byte[] data) {
super(data);
}
/**
* Sets the data for the system exclusive message. The
* first byte of the data array must be a valid system
* exclusive status byte (0xF0 or 0xF7).
* @param data the system exclusive message data
* @param length the length of the valid message data in
* the array, including the status byte.
*/
public void setMessage(byte[] data, int length) throws InvalidMidiDataException {
int status = (data[0] & 0xFF);
if ((status != 0xF0) && (status != 0xF7)) {
throw new InvalidMidiDataException("Invalid status byte for sysex message: 0x" + Integer.toHexString(status));
}
super.setMessage(data, length);
}
/**
* Sets the data for the system exclusive message.
* @param status the status byte for the message (0xF0 or 0xF7)
* @param data the system exclusive message data
* @param length the length of the valid message data in
* the array
* @throws InvalidMidiDataException if the status byte is invalid for a sysex message
*/
public void setMessage(int status, byte[] data, int length) throws InvalidMidiDataException {
if ( (status != 0xF0) && (status != 0xF7) ) {
throw new InvalidMidiDataException("Invalid status byte for sysex message: 0x" + Integer.toHexString(status));
}
if (length < 0 || length > data.length) {
throw new IndexOutOfBoundsException("length out of bounds: "+length);
}
this.length = length + 1;
if (this.data==null || this.data.length < this.length) {
this.data = new byte[this.length];
}
this.data[0] = (byte) (status & 0xFF);
if (length > 0) {
System.arraycopy(data, 0, this.data, 1, length);
}
}
/**
* Obtains a copy of the data for the system exclusive message.
* The returned array of bytes does not include the status byte.
* @return array containing the system exclusive message data.
*/
public byte[] getData() {
byte[] returnedArray = new byte[length - 1];
System.arraycopy(data, 1, returnedArray, 0, (length - 1));
return returnedArray;
}
/**
* Creates a new object of the same class and with the same contents
* as this object.
* @return a clone of this instance
*/
public Object clone() {
byte[] newData = new byte[length];
System.arraycopy(data, 0, newData, 0, newData.length);
SysexMessage event = new SysexMessage(newData);
return event;
}
}

View File

@@ -0,0 +1,275 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
import java.util.Vector;
import java.util.ArrayList;
import java.util.HashSet;
import com.sun.media.sound.MidiUtils;
/**
* A MIDI track is an independent stream of MIDI events (time-stamped MIDI
* data) that can be stored along with other tracks in a standard MIDI file.
* The MIDI specification allows only 16 channels of MIDI data, but tracks
* are a way to get around this limitation. A MIDI file can contain any number
* of tracks, each containing its own stream of up to 16 channels of MIDI data.
* <p>
* A <code>Track</code> occupies a middle level in the hierarchy of data played
* by a <code>{@link Sequencer}</code>: sequencers play sequences, which contain tracks,
* which contain MIDI events. A sequencer may provide controls that mute
* or solo individual tracks.
* <p>
* The timing information and resolution for a track is controlled by and stored
* in the sequence containing the track. A given <code>Track</code>
* is considered to belong to the particular <code>{@link Sequence}</code> that
* maintains its timing. For this reason, a new (empty) track is created by calling the
* <code>{@link Sequence#createTrack}</code> method, rather than by directly invoking a
* <code>Track</code> constructor.
* <p>
* The <code>Track</code> class provides methods to edit the track by adding
* or removing <code>MidiEvent</code> objects from it. These operations keep
* the event list in the correct time order. Methods are also
* included to obtain the track's size, in terms of either the number of events
* it contains or its duration in ticks.
*
* @see Sequencer#setTrackMute
* @see Sequencer#setTrackSolo
*
* @author Kara Kytle
* @author Florian Bomers
*/
public class Track {
// TODO: use arrays for faster access
// the list containing the events
private ArrayList eventsList = new ArrayList();
// use a hashset to detect duplicate events in add(MidiEvent)
private HashSet set = new HashSet();
private MidiEvent eotEvent;
/**
* Package-private constructor. Constructs a new, empty Track object,
* which initially contains one event, the meta-event End of Track.
*/
Track() {
// start with the end of track event
MetaMessage eot = new ImmutableEndOfTrack();
eotEvent = new MidiEvent(eot, 0);
eventsList.add(eotEvent);
set.add(eotEvent);
}
/**
* Adds a new event to the track. However, if the event is already
* contained in the track, it is not added again. The list of events
* is kept in time order, meaning that this event inserted at the
* appropriate place in the list, not necessarily at the end.
*
* @param event the event to add
* @return <code>true</code> if the event did not already exist in the
* track and was added, otherwise <code>false</code>
*/
public boolean add(MidiEvent event) {
if (event == null) {
return false;
}
synchronized(eventsList) {
if (!set.contains(event)) {
int eventsCount = eventsList.size();
// get the last event
MidiEvent lastEvent = null;
if (eventsCount > 0) {
lastEvent = (MidiEvent) eventsList.get(eventsCount - 1);
}
// sanity check that we have a correct end-of-track
if (lastEvent != eotEvent) {
// if there is no eot event, add our immutable instance again
if (lastEvent != null) {
// set eotEvent's tick to the last tick of the track
eotEvent.setTick(lastEvent.getTick());
} else {
// if the events list is empty, just set the tick to 0
eotEvent.setTick(0);
}
// we needn't check for a duplicate of eotEvent in "eventsList",
// since then it would appear in the set.
eventsList.add(eotEvent);
set.add(eotEvent);
eventsCount = eventsList.size();
}
// first see if we are trying to add
// and endoftrack event.
if (MidiUtils.isMetaEndOfTrack(event.getMessage())) {
// since end of track event is useful
// for delays at the end of a track, we want to keep
// the tick value requested here if it is greater
// than the one on the eot we are maintaining.
// Otherwise, we only want a single eot event, so ignore.
if (event.getTick() > eotEvent.getTick()) {
eotEvent.setTick(event.getTick());
}
return true;
}
// prevent duplicates
set.add(event);
// insert event such that events is sorted in increasing
// tick order
int i = eventsCount;
for ( ; i > 0; i--) {
if (event.getTick() >= ((MidiEvent)eventsList.get(i-1)).getTick()) {
break;
}
}
if (i == eventsCount) {
// we're adding an event after the
// tick value of our eot, so push the eot out.
// Always add at the end for better performance:
// this saves all the checks and arraycopy when inserting
// overwrite eot with new event
eventsList.set(eventsCount - 1, event);
// set new time of eot, if necessary
if (eotEvent.getTick() < event.getTick()) {
eotEvent.setTick(event.getTick());
}
// add eot again at the end
eventsList.add(eotEvent);
} else {
eventsList.add(i, event);
}
return true;
}
}
return false;
}
/**
* Removes the specified event from the track.
* @param event the event to remove
* @return <code>true</code> if the event existed in the track and was removed,
* otherwise <code>false</code>
*/
public boolean remove(MidiEvent event) {
// this implementation allows removing the EOT event.
// pretty bad, but would probably be too risky to
// change behavior now, in case someone does tricks like:
//
// while (track.size() > 0) track.remove(track.get(track.size() - 1));
// also, would it make sense to adjust the EOT's time
// to the last event, if the last non-EOT event is removed?
// Or: document that the ticks() length will not be reduced
// by deleting events (unless the EOT event is removed)
synchronized(eventsList) {
if (set.remove(event)) {
int i = eventsList.indexOf(event);
if (i >= 0) {
eventsList.remove(i);
return true;
}
}
}
return false;
}
/**
* Obtains the event at the specified index.
* @param index the location of the desired event in the event vector
* @throws ArrayIndexOutOfBoundsException if the
* specified index is negative or not less than the current size of
* this track.
* @see #size
* @return the event at the specified index
*/
public MidiEvent get(int index) throws ArrayIndexOutOfBoundsException {
try {
synchronized(eventsList) {
return (MidiEvent)eventsList.get(index);
}
} catch (IndexOutOfBoundsException ioobe) {
throw new ArrayIndexOutOfBoundsException(ioobe.getMessage());
}
}
/**
* Obtains the number of events in this track.
* @return the size of the track's event vector
*/
public int size() {
synchronized(eventsList) {
return eventsList.size();
}
}
/**
* Obtains the length of the track, expressed in MIDI ticks. (The
* duration of a tick in seconds is determined by the timing resolution
* of the <code>Sequence</code> containing this track, and also by
* the tempo of the music as set by the sequencer.)
* @return the duration, in ticks
* @see Sequence#Sequence(float, int)
* @see Sequencer#setTempoInBPM(float)
* @see Sequencer#getTickPosition()
*/
public long ticks() {
long ret = 0;
synchronized (eventsList) {
if (eventsList.size() > 0) {
ret = ((MidiEvent)eventsList.get(eventsList.size() - 1)).getTick();
}
}
return ret;
}
private static class ImmutableEndOfTrack extends MetaMessage {
private ImmutableEndOfTrack() {
super(new byte[3]);
data[0] = (byte) META;
data[1] = MidiUtils.META_END_OF_TRACK_TYPE;
data[2] = 0;
}
public void setMessage(int type, byte[] data, int length) throws InvalidMidiDataException {
throw new InvalidMidiDataException("cannot modify end of track message");
}
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* A <code>Transmitter</code> sends <code>{@link MidiEvent}</code> objects to one or more
* <code>{@link Receiver Receivers}</code>. Common MIDI transmitters include sequencers
* and MIDI input ports.
*
* @see Receiver
*
* @author Kara Kytle
*/
public interface Transmitter extends AutoCloseable {
/**
* Sets the receiver to which this transmitter will deliver MIDI messages.
* If a receiver is currently set, it is replaced with this one.
* @param receiver the desired receiver.
*/
public void setReceiver(Receiver receiver);
/**
* Obtains the current receiver to which this transmitter will deliver MIDI messages.
* @return the current receiver. If no receiver is currently set,
* returns <code>null</code>
*/
public Receiver getReceiver();
/**
* Indicates that the application has finished using the transmitter, and
* that limited resources it requires may be released or made available.
*
* <p>If the creation of this <code>Transmitter</code> resulted in
* implicitly opening the underlying device, the device is
* implicitly closed by this method. This is true unless the device is
* kept open by other <code>Receiver</code> or <code>Transmitter</code>
* instances that opened the device implicitly, and unless the device
* has been opened explicitly. If the device this
* <code>Transmitter</code> is retrieved from is closed explicitly
* by calling {@link MidiDevice#close MidiDevice.close}, the
* <code>Transmitter</code> is closed, too. For a detailed
* description of open/close behaviour see the class description
* of {@link javax.sound.midi.MidiDevice MidiDevice}.
*
* @see javax.sound.midi.MidiSystem#getTransmitter
*/
public void close();
}

View File

@@ -0,0 +1,160 @@
/*
* Copyright (c) 1998, 2002, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi;
/**
* A <code>VoiceStatus</code> object contains information about the current
* status of one of the voices produced by a {@link Synthesizer}.
* <p>
* MIDI synthesizers are generally capable of producing some maximum number of
* simultaneous notes, also referred to as voices. A voice is a stream
* of successive single notes, and the process of assigning incoming MIDI notes to
* specific voices is known as voice allocation.
* However, the voice-allocation algorithm and the contents of each voice are
* normally internal to a MIDI synthesizer and hidden from outside view. One can, of
* course, learn from MIDI messages which notes the synthesizer is playing, and
* one might be able deduce something about the assignment of notes to voices.
* But MIDI itself does not provide a means to report which notes a
* synthesizer has assigned to which voice, nor even to report how many voices
* the synthesizer is capable of synthesizing.
* <p>
* In Java Sound, however, a
* <code>Synthesizer</code> class can expose the contents of its voices through its
* {@link Synthesizer#getVoiceStatus() getVoiceStatus()} method.
* This behavior is recommended but optional;
* synthesizers that don't expose their voice allocation simply return a
* zero-length array. A <code>Synthesizer</code> that does report its voice status
* should maintain this information at
* all times for all of its voices, whether they are currently sounding or
* not. In other words, a given type of <code>Synthesizer</code> always has a fixed
* number of voices, equal to the maximum number of simultaneous notes it is
* capable of sounding.
* <p>
* <A NAME="description_of_active"></A>
* If the voice is not currently processing a MIDI note, it
* is considered inactive. A voice is inactive when it has
* been given no note-on commands, or when every note-on command received has
* been terminated by a corresponding note-off (or by an "all notes off"
* message). For example, this happens when a synthesizer capable of playing 16
* simultaneous notes is told to play a four-note chord; only
* four voices are active in this case (assuming no earlier notes are still playing).
* Usually, a voice whose status is reported as active is producing audible sound, but this
* is not always true; it depends on the details of the instrument (that
* is, the synthesis algorithm) and how long the note has been going on.
* For example, a voice may be synthesizing the sound of a single hand-clap. Because
* this sound dies away so quickly, it may become inaudible before a note-off
* message is received. In such a situation, the voice is still considered active
* even though no sound is currently being produced.
* <p>
* Besides its active or inactive status, the <code>VoiceStatus</code> class
* provides fields that reveal the voice's current MIDI channel, bank and
* program number, MIDI note number, and MIDI volume. All of these can
* change during the course of a voice. While the voice is inactive, each
* of these fields has an unspecified value, so you should check the active
* field first.
*
* @see Synthesizer#getMaxPolyphony
* @see Synthesizer#getVoiceStatus
*
* @author David Rivas
* @author Kara Kytle
*/
public class VoiceStatus {
/**
* Indicates whether the voice is currently processing a MIDI note.
* See the explanation of
* <A HREF="#description_of_active">active and inactive voices</A>.
*/
public boolean active = false;
/**
* The MIDI channel on which this voice is playing. The value is a
* zero-based channel number if the voice is active, or
* unspecified if the voice is inactive.
*
* @see MidiChannel
* @see #active
*/
public int channel = 0;
/**
* The bank number of the instrument that this voice is currently using.
* This is a number dictated by the MIDI bank-select message; it does not
* refer to a <code>SoundBank</code> object.
* The value ranges from 0 to 16383 if the voice is active, and is
* unspecified if the voice is inactive.
* @see Patch
* @see Soundbank
* @see #active
* @see MidiChannel#programChange(int, int)
*/
public int bank = 0;
/**
* The program number of the instrument that this voice is currently using.
* The value ranges from 0 to 127 if the voice is active, and is
* unspecified if the voice is inactive.
*
* @see MidiChannel#getProgram
* @see Patch
* @see #active
*/
public int program = 0;
/**
* The MIDI note that this voice is playing. The range for an active voice
* is from 0 to 127 in semitones, with 60 referring to Middle C.
* The value is unspecified if the voice is inactive.
*
* @see MidiChannel#noteOn
* @see #active
*/
public int note = 0;
/**
* The current MIDI volume level for the voice.
* The value ranges from 0 to 127 if the voice is active, and is
* unspecified if the voice is inactive.
* <p>
* Note that this value does not necessarily reflect
* the instantaneous level of the sound produced by this
* voice; that level is the result of many contributing
* factors, including the current instrument and the
* shape of the amplitude envelope it produces.
*
* @see #active
*/
public int volume = 0;
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi.spi;
import javax.sound.midi.MidiDevice;
/**
* A {@code MidiDeviceProvider} is a factory or provider for a particular type
* of MIDI device. This mechanism allows the implementation to determine how
* resources are managed in the creation and management of a device.
*
* @author Kara Kytle
*/
public abstract class MidiDeviceProvider {
/**
* Indicates whether the device provider supports the device represented by
* the specified device info object.
*
* @param info an info object that describes the device for which support
* is queried
* @return {@code true} if the specified device is supported, otherwise
* {@code false}
*/
public boolean isDeviceSupported(MidiDevice.Info info) {
MidiDevice.Info infos[] = getDeviceInfo();
for(int i=0; i<infos.length; i++) {
if( info.equals( infos[i] ) ) {
return true;
}
}
return false;
}
/**
* Obtains the set of info objects representing the device or devices
* provided by this {@code MidiDeviceProvider}.
*
* @return set of device info objects
*/
public abstract MidiDevice.Info[] getDeviceInfo();
/**
* Obtains an instance of the device represented by the info object.
*
* @param info an info object that describes the desired device
* @return device instance
* @throws IllegalArgumentException if the info object specified does not
* match the info object for a device supported by this
* {@code MidiDeviceProvider}
*/
public abstract MidiDevice getDevice(MidiDevice.Info info);
}

View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi.spi;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import javax.sound.midi.MidiFileFormat;
import javax.sound.midi.Sequence;
import javax.sound.midi.InvalidMidiDataException;
/**
* A {@code MidiFileReader} supplies MIDI file-reading services. Classes
* implementing this interface can parse the format information from one or more
* types of MIDI file, and can produce a {@link Sequence} object from files of
* these types.
*
* @author Kara Kytle
* @since 1.3
*/
public abstract class MidiFileReader {
/**
* Obtains the MIDI file format of the input stream provided. The stream
* must point to valid MIDI file data. In general, MIDI file readers may
* need to read some data from the stream before determining whether they
* support it. These parsers must be able to mark the stream, read enough
* data to determine whether they support the stream, and, if not, reset the
* stream's read pointer to its original position. If the input stream does
* not support this, this method may fail with an {@code IOException}.
*
* @param stream the input stream from which file format information
* should be extracted
* @return a {@code MidiFileFormat} object describing the MIDI file format
* @throws InvalidMidiDataException if the stream does not point to valid
* MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs
* @see InputStream#markSupported
* @see InputStream#mark
*/
public abstract MidiFileFormat getMidiFileFormat(InputStream stream)
throws InvalidMidiDataException, IOException;
/**
* Obtains the MIDI file format of the URL provided. The URL must point to
* valid MIDI file data.
*
* @param url the URL from which file format information should be
* extracted
* @return a {@code MidiFileFormat} object describing the MIDI file format
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public abstract MidiFileFormat getMidiFileFormat(URL url)
throws InvalidMidiDataException, IOException;
/**
* Obtains the MIDI file format of the {@code File} provided. The
* {@code File} must point to valid MIDI file data.
*
* @param file the {@code File} from which file format information should
* be extracted
* @return a {@code MidiFileFormat} object describing the MIDI file format
* @throws InvalidMidiDataException if the {@code File} does not point to
* valid MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public abstract MidiFileFormat getMidiFileFormat(File file)
throws InvalidMidiDataException, IOException;
/**
* Obtains a MIDI sequence from the input stream provided. The stream must
* point to valid MIDI file data. In general, MIDI file readers may need to
* read some data from the stream before determining whether they support
* it. These parsers must be able to mark the stream, read enough data to
* determine whether they support the stream, and, if not, reset the
* stream's read pointer to its original position. If the input stream does
* not support this, this method may fail with an IOException.
*
* @param stream the input stream from which the {@code Sequence} should
* be constructed
* @return a {@code Sequence} object based on the MIDI file data contained
* in the input stream.
* @throws InvalidMidiDataException if the stream does not point to valid
* MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs
* @see InputStream#markSupported
* @see InputStream#mark
*/
public abstract Sequence getSequence(InputStream stream)
throws InvalidMidiDataException, IOException;
/**
* Obtains a MIDI sequence from the URL provided. The URL must point to
* valid MIDI file data.
*
* @param url the URL for which the {@code Sequence} should be constructed
* @return a {@code Sequence} object based on the MIDI file data pointed to
* by the URL
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public abstract Sequence getSequence(URL url)
throws InvalidMidiDataException, IOException;
/**
* Obtains a MIDI sequence from the {@code File} provided. The {@code File}
* must point to valid MIDI file data.
*
* @param file the {@code File} from which the {@code Sequence} should be
* constructed
* @return a {@code Sequence} object based on the MIDI file data pointed to
* by the {@code File}
* @throws InvalidMidiDataException if the {@code File} does not point to
* valid MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public abstract Sequence getSequence(File file)
throws InvalidMidiDataException, IOException;
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi.spi;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import javax.sound.midi.Sequence;
/**
* A {@code MidiFileWriter} supplies MIDI file-writing services. Classes that
* implement this interface can write one or more types of MIDI file from a
* {@link Sequence} object.
*
* @author Kara Kytle
* @since 1.3
*/
public abstract class MidiFileWriter {
/**
* Obtains the set of MIDI file types for which file writing support is
* provided by this file writer.
*
* @return array of file types. If no file types are supported, an array of
* length 0 is returned.
*/
public abstract int[] getMidiFileTypes();
/**
* Obtains the file types that this file writer can write from the sequence
* specified.
*
* @param sequence the sequence for which MIDI file type support is
* queried
* @return array of file types. If no file types are supported, returns an
* array of length 0.
*/
public abstract int[] getMidiFileTypes(Sequence sequence);
/**
* Indicates whether file writing support for the specified MIDI file type
* is provided by this file writer.
*
* @param fileType the file type for which write capabilities are queried
* @return {@code true} if the file type is supported, otherwise
* {@code false}
*/
public boolean isFileTypeSupported(int fileType) {
int types[] = getMidiFileTypes();
for(int i=0; i<types.length; i++) {
if( fileType == types[i] ) {
return true;
}
}
return false;
}
/**
* Indicates whether a MIDI file of the file type specified can be written
* from the sequence indicated.
*
* @param fileType the file type for which write capabilities are queried
* @param sequence the sequence for which file writing support is queried
* @return {@code true} if the file type is supported for this sequence,
* otherwise {@code false}
*/
public boolean isFileTypeSupported(int fileType, Sequence sequence) {
int types[] = getMidiFileTypes( sequence );
for(int i=0; i<types.length; i++) {
if( fileType == types[i] ) {
return true;
}
}
return false;
}
/**
* Writes a stream of bytes representing a MIDI file of the file type
* indicated to the output stream provided.
*
* @param in sequence containing MIDI data to be written to the file
* @param fileType type of the file to be written to the output stream
* @param out stream to which the file data should be written
* @return the number of bytes written to the output stream
* @throws IOException if an I/O exception occurs
* @throws IllegalArgumentException if the file type is not supported by
* this file writer
* @see #isFileTypeSupported(int, Sequence)
* @see #getMidiFileTypes(Sequence)
*/
public abstract int write(Sequence in, int fileType, OutputStream out)
throws IOException;
/**
* Writes a stream of bytes representing a MIDI file of the file type
* indicated to the external file provided.
*
* @param in sequence containing MIDI data to be written to the external
* file
* @param fileType type of the file to be written to the external file
* @param out external file to which the file data should be written
* @return the number of bytes written to the file
* @throws IOException if an I/O exception occurs
* @throws IllegalArgumentException if the file type is not supported by
* this file writer
* @see #isFileTypeSupported(int, Sequence)
* @see #getMidiFileTypes(Sequence)
*/
public abstract int write(Sequence in, int fileType, File out)
throws IOException;
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.midi.spi;
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;
/**
* A {@code SoundbankReader} supplies soundbank file-reading services. Concrete
* subclasses of {@code SoundbankReader} parse a given soundbank file, producing
* a {@link javax.sound.midi.Soundbank} object that can be loaded into a
* {@link javax.sound.midi.Synthesizer}.
*
* @since 1.3
* @author Kara Kytle
*/
public abstract class SoundbankReader {
/**
* Obtains a soundbank object from the URL provided.
*
* @param url URL representing the soundbank.
* @return soundbank object
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
* soundbank data recognized by this soundbank reader
* @throws IOException if an I/O error occurs
*/
public abstract Soundbank getSoundbank(URL url)
throws InvalidMidiDataException, IOException;
/**
* Obtains a soundbank object from the {@code InputStream} provided.
*
* @param stream {@code InputStream} representing the soundbank
* @return soundbank object
* @throws InvalidMidiDataException if the stream does not point to valid
* MIDI soundbank data recognized by this soundbank reader
* @throws IOException if an I/O error occurs
*/
public abstract Soundbank getSoundbank(InputStream stream)
throws InvalidMidiDataException, IOException;
/**
* Obtains a soundbank object from the {@code File} provided.
*
* @param file the {@code File} representing the soundbank
* @return soundbank object
* @throws InvalidMidiDataException if the file does not point to valid MIDI
* soundbank data recognized by this soundbank reader
* @throws IOException if an I/O error occurs
*/
public abstract Soundbank getSoundbank(File file)
throws InvalidMidiDataException, IOException;
}

View File

@@ -0,0 +1,418 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
import java.io.File;
import java.io.OutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* An instance of the <code>AudioFileFormat</code> class describes
* an audio file, including the file type, the file's length in bytes,
* the length in sample frames of the audio data contained in the file,
* and the format of the audio data.
* <p>
* The <code>{@link AudioSystem}</code> class includes methods for determining the format
* of an audio file, obtaining an audio input stream from an audio file, and
* writing an audio file from an audio input stream.
*
* <p>An <code>AudioFileFormat</code> object can
* include a set of properties. A property is a pair of key and value:
* the key is of type <code>String</code>, the associated property
* value is an arbitrary object.
* Properties specify additional informational
* meta data (like a author, copyright, or file duration).
* Properties are optional information, and file reader and file
* writer implementations are not required to provide or
* recognize properties.
*
* <p>The following table lists some common properties that should
* be used in implementations:
*
* <table border=1>
* <caption>Audio File Format Properties</caption>
* <tr>
* <th>Property key</th>
* <th>Value type</th>
* <th>Description</th>
* </tr>
* <tr>
* <td>&quot;duration&quot;</td>
* <td>{@link java.lang.Long Long}</td>
* <td>playback duration of the file in microseconds</td>
* </tr>
* <tr>
* <td>&quot;author&quot;</td>
* <td>{@link java.lang.String String}</td>
* <td>name of the author of this file</td>
* </tr>
* <tr>
* <td>&quot;title&quot;</td>
* <td>{@link java.lang.String String}</td>
* <td>title of this file</td>
* </tr>
* <tr>
* <td>&quot;copyright&quot;</td>
* <td>{@link java.lang.String String}</td>
* <td>copyright message</td>
* </tr>
* <tr>
* <td>&quot;date&quot;</td>
* <td>{@link java.util.Date Date}</td>
* <td>date of the recording or release</td>
* </tr>
* <tr>
* <td>&quot;comment&quot;</td>
* <td>{@link java.lang.String String}</td>
* <td>an arbitrary text</td>
* </tr>
* </table>
*
*
* @author David Rivas
* @author Kara Kytle
* @author Florian Bomers
* @see AudioInputStream
* @since 1.3
*/
public class AudioFileFormat {
// INSTANCE VARIABLES
/**
* File type.
*/
private Type type;
/**
* File length in bytes
*/
private int byteLength;
/**
* Format of the audio data contained in the file.
*/
private AudioFormat format;
/**
* Audio data length in sample frames
*/
private int frameLength;
/** The set of properties */
private HashMap<String, Object> properties;
/**
* Constructs an audio file format object.
* This protected constructor is intended for use by providers of file-reading
* services when returning information about an audio file or about supported audio file
* formats.
* @param type the type of the audio file
* @param byteLength the length of the file in bytes, or <code>AudioSystem.NOT_SPECIFIED</code>
* @param format the format of the audio data contained in the file
* @param frameLength the audio data length in sample frames, or <code>AudioSystem.NOT_SPECIFIED</code>
*
* @see #getType
*/
protected AudioFileFormat(Type type, int byteLength, AudioFormat format, int frameLength) {
this.type = type;
this.byteLength = byteLength;
this.format = format;
this.frameLength = frameLength;
this.properties = null;
}
/**
* Constructs an audio file format object.
* This public constructor may be used by applications to describe the
* properties of a requested audio file.
* @param type the type of the audio file
* @param format the format of the audio data contained in the file
* @param frameLength the audio data length in sample frames, or <code>AudioSystem.NOT_SPECIFIED</code>
*/
public AudioFileFormat(Type type, AudioFormat format, int frameLength) {
this(type,AudioSystem.NOT_SPECIFIED,format,frameLength);
}
/**
* Construct an audio file format object with a set of
* defined properties.
* This public constructor may be used by applications to describe the
* properties of a requested audio file. The properties map
* will be copied to prevent any changes to it.
*
* @param type the type of the audio file
* @param format the format of the audio data contained in the file
* @param frameLength the audio data length in sample frames, or
* <code>AudioSystem.NOT_SPECIFIED</code>
* @param properties a <code>Map&lt;String,Object&gt;</code> object
* with properties
*
* @since 1.5
*/
public AudioFileFormat(Type type, AudioFormat format,
int frameLength, Map<String, Object> properties) {
this(type,AudioSystem.NOT_SPECIFIED,format,frameLength);
this.properties = new HashMap<String, Object>(properties);
}
/**
* Obtains the audio file type, such as <code>WAVE</code> or <code>AU</code>.
* @return the audio file type
*
* @see Type#WAVE
* @see Type#AU
* @see Type#AIFF
* @see Type#AIFC
* @see Type#SND
*/
public Type getType() {
return type;
}
/**
* Obtains the size in bytes of the entire audio file (not just its audio data).
* @return the audio file length in bytes
* @see AudioSystem#NOT_SPECIFIED
*/
public int getByteLength() {
return byteLength;
}
/**
* Obtains the format of the audio data contained in the audio file.
* @return the audio data format
*/
public AudioFormat getFormat() {
return format;
}
/**
* Obtains the length of the audio data contained in the file, expressed in sample frames.
* @return the number of sample frames of audio data in the file
* @see AudioSystem#NOT_SPECIFIED
*/
public int getFrameLength() {
return frameLength;
}
/**
* Obtain an unmodifiable map of properties.
* The concept of properties is further explained in
* the {@link AudioFileFormat class description}.
*
* @return a <code>Map&lt;String,Object&gt;</code> object containing
* all properties. If no properties are recognized, an empty map is
* returned.
*
* @see #getProperty(String)
* @since 1.5
*/
public Map<String,Object> properties() {
Map<String,Object> ret;
if (properties == null) {
ret = new HashMap<String,Object>(0);
} else {
ret = (Map<String,Object>) (properties.clone());
}
return (Map<String,Object>) Collections.unmodifiableMap(ret);
}
/**
* Obtain the property value specified by the key.
* The concept of properties is further explained in
* the {@link AudioFileFormat class description}.
*
* <p>If the specified property is not defined for a
* particular file format, this method returns
* <code>null</code>.
*
* @param key the key of the desired property
* @return the value of the property with the specified key,
* or <code>null</code> if the property does not exist.
*
* @see #properties()
* @since 1.5
*/
public Object getProperty(String key) {
if (properties == null) {
return null;
}
return properties.get(key);
}
/**
* Provides a string representation of the file format.
* @return the file format as a string
*/
public String toString() {
StringBuffer buf = new StringBuffer();
//$$fb2002-11-01: fix for 4672864: AudioFileFormat.toString() throws unexpected NullPointerException
if (type != null) {
buf.append(type.toString() + " (." + type.getExtension() + ") file");
} else {
buf.append("unknown file format");
}
if (byteLength != AudioSystem.NOT_SPECIFIED) {
buf.append(", byte length: " + byteLength);
}
buf.append(", data format: " + format);
if (frameLength != AudioSystem.NOT_SPECIFIED) {
buf.append(", frame length: " + frameLength);
}
return new String(buf);
}
/**
* An instance of the <code>Type</code> class represents one of the
* standard types of audio file. Static instances are provided for the
* common types.
*/
public static class Type {
// FILE FORMAT TYPE DEFINES
/**
* Specifies a WAVE file.
*/
public static final Type WAVE = new Type("WAVE", "wav");
/**
* Specifies an AU file.
*/
public static final Type AU = new Type("AU", "au");
/**
* Specifies an AIFF file.
*/
public static final Type AIFF = new Type("AIFF", "aif");
/**
* Specifies an AIFF-C file.
*/
public static final Type AIFC = new Type("AIFF-C", "aifc");
/**
* Specifies a SND file.
*/
public static final Type SND = new Type("SND", "snd");
// INSTANCE VARIABLES
/**
* File type name.
*/
private final String name;
/**
* File type extension.
*/
private final String extension;
// CONSTRUCTOR
/**
* Constructs a file type.
* @param name the string that names the file type
* @param extension the string that commonly marks the file type
* without leading dot.
*/
public Type(String name, String extension) {
this.name = name;
this.extension = extension;
}
// METHODS
/**
* Finalizes the equals method
*/
public final boolean equals(Object obj) {
if (toString() == null) {
return (obj != null) && (obj.toString() == null);
}
if (obj instanceof Type) {
return toString().equals(obj.toString());
}
return false;
}
/**
* Finalizes the hashCode method
*/
public final int hashCode() {
if (toString() == null) {
return 0;
}
return toString().hashCode();
}
/**
* Provides the file type's name as the <code>String</code> representation
* of the file type.
* @return the file type's name
*/
public final String toString() {
return name;
}
/**
* Obtains the common file name extension for this file type.
* @return file type extension
*/
public String getExtension() {
return extension;
}
} // class Type
} // class AudioFileFormat

View File

@@ -0,0 +1,670 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* <code>AudioFormat</code> is the class that specifies a particular arrangement of data in a sound stream.
* By examining the information stored in the audio format, you can discover how to interpret the bits in the
* binary sound data.
* <p>
* Every data line has an audio format associated with its data stream. The audio format of a source (playback) data line indicates
* what kind of data the data line expects to receive for output. For a target (capture) data line, the audio format specifies the kind
* of the data that can be read from the line.
* Sound files also have audio formats, of course. The <code>{@link AudioFileFormat}</code>
* class encapsulates an <code>AudioFormat</code> in addition to other,
* file-specific information. Similarly, an <code>{@link AudioInputStream}</code> has an
* <code>AudioFormat</code>.
* <p>
* The <code>AudioFormat</code> class accommodates a number of common sound-file encoding techniques, including
* pulse-code modulation (PCM), mu-law encoding, and a-law encoding. These encoding techniques are predefined,
* but service providers can create new encoding types.
* The encoding that a specific format uses is named by its <code>encoding</code> field.
*<p>
* In addition to the encoding, the audio format includes other properties that further specify the exact
* arrangement of the data.
* These include the number of channels, sample rate, sample size, byte order, frame rate, and frame size.
* Sounds may have different numbers of audio channels: one for mono, two for stereo.
* The sample rate measures how many "snapshots" (samples) of the sound pressure are taken per second, per channel.
* (If the sound is stereo rather than mono, two samples are actually measured at each instant of time: one for the left channel,
* and another for the right channel; however, the sample rate still measures the number per channel, so the rate is the same
* regardless of the number of channels. This is the standard use of the term.)
* The sample size indicates how many bits are used to store each snapshot; 8 and 16 are typical values.
* For 16-bit samples (or any other sample size larger than a byte),
* byte order is important; the bytes in each sample are arranged in
* either the "little-endian" or "big-endian" style.
* For encodings like PCM, a frame consists of the set of samples for all channels at a given
* point in time, and so the size of a frame (in bytes) is always equal to the size of a sample (in bytes) times
* the number of channels. However, with some other sorts of encodings a frame can contain
* a bundle of compressed data for a whole series of samples, as well as additional, non-sample
* data. For such encodings, the sample rate and sample size refer to the data after it is decoded into PCM,
* and so they are completely different from the frame rate and frame size.
*
* <p>An <code>AudioFormat</code> object can include a set of
* properties. A property is a pair of key and value: the key
* is of type <code>String</code>, the associated property
* value is an arbitrary object. Properties specify
* additional format specifications, like the bit rate for
* compressed formats. Properties are mainly used as a means
* to transport additional information of the audio format
* to and from the service providers. Therefore, properties
* are ignored in the {@link #matches(AudioFormat)} method.
* However, methods which rely on the installed service
* providers, like {@link AudioSystem#isConversionSupported
* (AudioFormat, AudioFormat) isConversionSupported} may consider
* properties, depending on the respective service provider
* implementation.
*
* <p>The following table lists some common properties which
* service providers should use, if applicable:
*
* <table border=0>
* <caption>Audio Format Properties</caption>
* <tr>
* <th>Property key</th>
* <th>Value type</th>
* <th>Description</th>
* </tr>
* <tr>
* <td>&quot;bitrate&quot;</td>
* <td>{@link java.lang.Integer Integer}</td>
* <td>average bit rate in bits per second</td>
* </tr>
* <tr>
* <td>&quot;vbr&quot;</td>
* <td>{@link java.lang.Boolean Boolean}</td>
* <td><code>true</code>, if the file is encoded in variable bit
* rate (VBR)</td>
* </tr>
* <tr>
* <td>&quot;quality&quot;</td>
* <td>{@link java.lang.Integer Integer}</td>
* <td>encoding/conversion quality, 1..100</td>
* </tr>
* </table>
*
* <p>Vendors of service providers (plugins) are encouraged
* to seek information about other already established
* properties in third party plugins, and follow the same
* conventions.
*
* @author Kara Kytle
* @author Florian Bomers
* @see DataLine#getFormat
* @see AudioInputStream#getFormat
* @see AudioFileFormat
* @see javax.sound.sampled.spi.FormatConversionProvider
* @since 1.3
*/
public class AudioFormat {
// INSTANCE VARIABLES
/**
* The audio encoding technique used by this format.
*/
protected Encoding encoding;
/**
* The number of samples played or recorded per second, for sounds that have this format.
*/
protected float sampleRate;
/**
* The number of bits in each sample of a sound that has this format.
*/
protected int sampleSizeInBits;
/**
* The number of audio channels in this format (1 for mono, 2 for stereo).
*/
protected int channels;
/**
* The number of bytes in each frame of a sound that has this format.
*/
protected int frameSize;
/**
* The number of frames played or recorded per second, for sounds that have this format.
*/
protected float frameRate;
/**
* Indicates whether the audio data is stored in big-endian or little-endian order.
*/
protected boolean bigEndian;
/** The set of properties */
private HashMap<String, Object> properties;
/**
* Constructs an <code>AudioFormat</code> with the given parameters.
* The encoding specifies the convention used to represent the data.
* The other parameters are further explained in the {@link AudioFormat
* class description}.
* @param encoding the audio encoding technique
* @param sampleRate the number of samples per second
* @param sampleSizeInBits the number of bits in each sample
* @param channels the number of channels (1 for mono, 2 for stereo, and so on)
* @param frameSize the number of bytes in each frame
* @param frameRate the number of frames per second
* @param bigEndian indicates whether the data for a single sample
* is stored in big-endian byte order (<code>false</code>
* means little-endian)
*/
public AudioFormat(Encoding encoding, float sampleRate, int sampleSizeInBits,
int channels, int frameSize, float frameRate, boolean bigEndian) {
this.encoding = encoding;
this.sampleRate = sampleRate;
this.sampleSizeInBits = sampleSizeInBits;
this.channels = channels;
this.frameSize = frameSize;
this.frameRate = frameRate;
this.bigEndian = bigEndian;
this.properties = null;
}
/**
* Constructs an <code>AudioFormat</code> with the given parameters.
* The encoding specifies the convention used to represent the data.
* The other parameters are further explained in the {@link AudioFormat
* class description}.
* @param encoding the audio encoding technique
* @param sampleRate the number of samples per second
* @param sampleSizeInBits the number of bits in each sample
* @param channels the number of channels (1 for mono, 2 for
* stereo, and so on)
* @param frameSize the number of bytes in each frame
* @param frameRate the number of frames per second
* @param bigEndian indicates whether the data for a single sample
* is stored in big-endian byte order
* (<code>false</code> means little-endian)
* @param properties a <code>Map&lt;String,Object&gt;</code> object
* containing format properties
*
* @since 1.5
*/
public AudioFormat(Encoding encoding, float sampleRate,
int sampleSizeInBits, int channels,
int frameSize, float frameRate,
boolean bigEndian, Map<String, Object> properties) {
this(encoding, sampleRate, sampleSizeInBits, channels,
frameSize, frameRate, bigEndian);
this.properties = new HashMap<String, Object>(properties);
}
/**
* Constructs an <code>AudioFormat</code> with a linear PCM encoding and
* the given parameters. The frame size is set to the number of bytes
* required to contain one sample from each channel, and the frame rate
* is set to the sample rate.
*
* @param sampleRate the number of samples per second
* @param sampleSizeInBits the number of bits in each sample
* @param channels the number of channels (1 for mono, 2 for stereo, and so on)
* @param signed indicates whether the data is signed or unsigned
* @param bigEndian indicates whether the data for a single sample
* is stored in big-endian byte order (<code>false</code>
* means little-endian)
*/
public AudioFormat(float sampleRate, int sampleSizeInBits,
int channels, boolean signed, boolean bigEndian) {
this((signed == true ? Encoding.PCM_SIGNED : Encoding.PCM_UNSIGNED),
sampleRate,
sampleSizeInBits,
channels,
(channels == AudioSystem.NOT_SPECIFIED || sampleSizeInBits == AudioSystem.NOT_SPECIFIED)?
AudioSystem.NOT_SPECIFIED:
((sampleSizeInBits + 7) / 8) * channels,
sampleRate,
bigEndian);
}
/**
* Obtains the type of encoding for sounds in this format.
*
* @return the encoding type
* @see Encoding#PCM_SIGNED
* @see Encoding#PCM_UNSIGNED
* @see Encoding#ULAW
* @see Encoding#ALAW
*/
public Encoding getEncoding() {
return encoding;
}
/**
* Obtains the sample rate.
* For compressed formats, the return value is the sample rate of the uncompressed
* audio data.
* When this AudioFormat is used for queries (e.g. {@link
* AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
* AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
* DataLine.Info#getFormats() DataLine.Info.getFormats}), a sample rate of
* <code>AudioSystem.NOT_SPECIFIED</code> means that any sample rate is
* acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
* the sample rate is not defined for this audio format.
* @return the number of samples per second,
* or <code>AudioSystem.NOT_SPECIFIED</code>
*
* @see #getFrameRate()
* @see AudioSystem#NOT_SPECIFIED
*/
public float getSampleRate() {
return sampleRate;
}
/**
* Obtains the size of a sample.
* For compressed formats, the return value is the sample size of the
* uncompressed audio data.
* When this AudioFormat is used for queries (e.g. {@link
* AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
* AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
* DataLine.Info#getFormats() DataLine.Info.getFormats}), a sample size of
* <code>AudioSystem.NOT_SPECIFIED</code> means that any sample size is
* acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
* the sample size is not defined for this audio format.
* @return the number of bits in each sample,
* or <code>AudioSystem.NOT_SPECIFIED</code>
*
* @see #getFrameSize()
* @see AudioSystem#NOT_SPECIFIED
*/
public int getSampleSizeInBits() {
return sampleSizeInBits;
}
/**
* Obtains the number of channels.
* When this AudioFormat is used for queries (e.g. {@link
* AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
* AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
* DataLine.Info#getFormats() DataLine.Info.getFormats}), a return value of
* <code>AudioSystem.NOT_SPECIFIED</code> means that any (positive) number of channels is
* acceptable.
* @return The number of channels (1 for mono, 2 for stereo, etc.),
* or <code>AudioSystem.NOT_SPECIFIED</code>
*
* @see AudioSystem#NOT_SPECIFIED
*/
public int getChannels() {
return channels;
}
/**
* Obtains the frame size in bytes.
* When this AudioFormat is used for queries (e.g. {@link
* AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
* AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
* DataLine.Info#getFormats() DataLine.Info.getFormats}), a frame size of
* <code>AudioSystem.NOT_SPECIFIED</code> means that any frame size is
* acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
* the frame size is not defined for this audio format.
* @return the number of bytes per frame,
* or <code>AudioSystem.NOT_SPECIFIED</code>
*
* @see #getSampleSizeInBits()
* @see AudioSystem#NOT_SPECIFIED
*/
public int getFrameSize() {
return frameSize;
}
/**
* Obtains the frame rate in frames per second.
* When this AudioFormat is used for queries (e.g. {@link
* AudioSystem#isConversionSupported(AudioFormat, AudioFormat)
* AudioSystem.isConversionSupported}) or capabilities (e.g. {@link
* DataLine.Info#getFormats() DataLine.Info.getFormats}), a frame rate of
* <code>AudioSystem.NOT_SPECIFIED</code> means that any frame rate is
* acceptable. <code>AudioSystem.NOT_SPECIFIED</code> is also returned when
* the frame rate is not defined for this audio format.
* @return the number of frames per second,
* or <code>AudioSystem.NOT_SPECIFIED</code>
*
* @see #getSampleRate()
* @see AudioSystem#NOT_SPECIFIED
*/
public float getFrameRate() {
return frameRate;
}
/**
* Indicates whether the audio data is stored in big-endian or little-endian
* byte order. If the sample size is not more than one byte, the return value is
* irrelevant.
* @return <code>true</code> if the data is stored in big-endian byte order,
* <code>false</code> if little-endian
*/
public boolean isBigEndian() {
return bigEndian;
}
/**
* Obtain an unmodifiable map of properties.
* The concept of properties is further explained in
* the {@link AudioFileFormat class description}.
*
* @return a <code>Map&lt;String,Object&gt;</code> object containing
* all properties. If no properties are recognized, an empty map is
* returned.
*
* @see #getProperty(String)
* @since 1.5
*/
public Map<String,Object> properties() {
Map<String,Object> ret;
if (properties == null) {
ret = new HashMap<String,Object>(0);
} else {
ret = (Map<String,Object>) (properties.clone());
}
return (Map<String,Object>) Collections.unmodifiableMap(ret);
}
/**
* Obtain the property value specified by the key.
* The concept of properties is further explained in
* the {@link AudioFileFormat class description}.
*
* <p>If the specified property is not defined for a
* particular file format, this method returns
* <code>null</code>.
*
* @param key the key of the desired property
* @return the value of the property with the specified key,
* or <code>null</code> if the property does not exist.
*
* @see #properties()
* @since 1.5
*/
public Object getProperty(String key) {
if (properties == null) {
return null;
}
return properties.get(key);
}
/**
* Indicates whether this format matches the one specified.
* To match, two formats must have the same encoding,
* and consistent values of the number of channels, sample rate, sample size,
* frame rate, and frame size.
* The values of the property are consistent if they are equal
* or the specified format has the property value
* {@code AudioSystem.NOT_SPECIFIED}.
* The byte order (big-endian or little-endian) must be the same
* if the sample size is greater than one byte.
*
* @param format format to test for match
* @return {@code true} if this format matches the one specified,
* {@code false} otherwise.
*/
public boolean matches(AudioFormat format) {
if (format.getEncoding().equals(getEncoding())
&& (format.getChannels() == AudioSystem.NOT_SPECIFIED
|| format.getChannels() == getChannels())
&& (format.getSampleRate() == (float)AudioSystem.NOT_SPECIFIED
|| format.getSampleRate() == getSampleRate())
&& (format.getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED
|| format.getSampleSizeInBits() == getSampleSizeInBits())
&& (format.getFrameRate() == (float)AudioSystem.NOT_SPECIFIED
|| format.getFrameRate() == getFrameRate())
&& (format.getFrameSize() == AudioSystem.NOT_SPECIFIED
|| format.getFrameSize() == getFrameSize())
&& (getSampleSizeInBits() <= 8
|| format.isBigEndian() == isBigEndian())) {
return true;
}
return false;
}
/**
* Returns a string that describes the format, such as:
* "PCM SIGNED 22050 Hz 16 bit mono big-endian". The contents of the string
* may vary between implementations of Java Sound.
*
* @return a string that describes the format parameters
*/
public String toString() {
String sEncoding = "";
if (getEncoding() != null) {
sEncoding = getEncoding().toString() + " ";
}
String sSampleRate;
if (getSampleRate() == (float) AudioSystem.NOT_SPECIFIED) {
sSampleRate = "unknown sample rate, ";
} else {
sSampleRate = "" + getSampleRate() + " Hz, ";
}
String sSampleSizeInBits;
if (getSampleSizeInBits() == (float) AudioSystem.NOT_SPECIFIED) {
sSampleSizeInBits = "unknown bits per sample, ";
} else {
sSampleSizeInBits = "" + getSampleSizeInBits() + " bit, ";
}
String sChannels;
if (getChannels() == 1) {
sChannels = "mono, ";
} else
if (getChannels() == 2) {
sChannels = "stereo, ";
} else {
if (getChannels() == AudioSystem.NOT_SPECIFIED) {
sChannels = " unknown number of channels, ";
} else {
sChannels = ""+getChannels()+" channels, ";
}
}
String sFrameSize;
if (getFrameSize() == (float) AudioSystem.NOT_SPECIFIED) {
sFrameSize = "unknown frame size, ";
} else {
sFrameSize = "" + getFrameSize()+ " bytes/frame, ";
}
String sFrameRate = "";
if (Math.abs(getSampleRate() - getFrameRate()) > 0.00001) {
if (getFrameRate() == (float) AudioSystem.NOT_SPECIFIED) {
sFrameRate = "unknown frame rate, ";
} else {
sFrameRate = getFrameRate() + " frames/second, ";
}
}
String sEndian = "";
if ((getEncoding().equals(Encoding.PCM_SIGNED)
|| getEncoding().equals(Encoding.PCM_UNSIGNED))
&& ((getSampleSizeInBits() > 8)
|| (getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED))) {
if (isBigEndian()) {
sEndian = "big-endian";
} else {
sEndian = "little-endian";
}
}
return sEncoding
+ sSampleRate
+ sSampleSizeInBits
+ sChannels
+ sFrameSize
+ sFrameRate
+ sEndian;
}
/**
* The <code>Encoding</code> class names the specific type of data representation
* used for an audio stream. The encoding includes aspects of the
* sound format other than the number of channels, sample rate, sample size,
* frame rate, frame size, and byte order.
* <p>
* One ubiquitous type of audio encoding is pulse-code modulation (PCM),
* which is simply a linear (proportional) representation of the sound
* waveform. With PCM, the number stored in each sample is proportional
* to the instantaneous amplitude of the sound pressure at that point in
* time. The numbers may be signed or unsigned integers or floats.
* Besides PCM, other encodings include mu-law and a-law, which are nonlinear
* mappings of the sound amplitude that are often used for recording speech.
* <p>
* You can use a predefined encoding by referring to one of the static
* objects created by this class, such as PCM_SIGNED or
* PCM_UNSIGNED. Service providers can create new encodings, such as
* compressed audio formats, and make
* these available through the <code>{@link AudioSystem}</code> class.
* <p>
* The <code>Encoding</code> class is static, so that all
* <code>AudioFormat</code> objects that have the same encoding will refer
* to the same object (rather than different instances of the same class).
* This allows matches to be made by checking that two format's encodings
* are equal.
*
* @see AudioFormat
* @see javax.sound.sampled.spi.FormatConversionProvider
*
* @author Kara Kytle
* @since 1.3
*/
public static class Encoding {
// ENCODING DEFINES
/**
* Specifies signed, linear PCM data.
*/
public static final Encoding PCM_SIGNED = new Encoding("PCM_SIGNED");
/**
* Specifies unsigned, linear PCM data.
*/
public static final Encoding PCM_UNSIGNED = new Encoding("PCM_UNSIGNED");
/**
* Specifies floating-point PCM data.
*
* @since 1.7
*/
public static final Encoding PCM_FLOAT = new Encoding("PCM_FLOAT");
/**
* Specifies u-law encoded data.
*/
public static final Encoding ULAW = new Encoding("ULAW");
/**
* Specifies a-law encoded data.
*/
public static final Encoding ALAW = new Encoding("ALAW");
// INSTANCE VARIABLES
/**
* Encoding name.
*/
private String name;
// CONSTRUCTOR
/**
* Constructs a new encoding.
* @param name the name of the new type of encoding
*/
public Encoding(String name) {
this.name = name;
}
// METHODS
/**
* Finalizes the equals method
*/
public final boolean equals(Object obj) {
if (toString() == null) {
return (obj != null) && (obj.toString() == null);
}
if (obj instanceof Encoding) {
return toString().equals(obj.toString());
}
return false;
}
/**
* Finalizes the hashCode method
*/
public final int hashCode() {
if (toString() == null) {
return 0;
}
return toString().hashCode();
}
/**
* Provides the <code>String</code> representation of the encoding. This <code>String</code> is
* the same name that was passed to the constructor. For the predefined encodings, the name
* is similar to the encoding's variable (field) name. For example, <code>PCM_SIGNED.toString()</code> returns
* the name "pcm_signed".
*
* @return the encoding name
*/
public final String toString() {
return name;
}
} // class Encoding
}

View File

@@ -0,0 +1,515 @@
/*
* Copyright (c) 1999, 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.io.IOException;
/**
* An audio input stream is an input stream with a specified audio format and
* length. The length is expressed in sample frames, not bytes.
* Several methods are provided for reading a certain number of bytes from
* the stream, or an unspecified number of bytes.
* The audio input stream keeps track of the last byte that was read.
* You can skip over an arbitrary number of bytes to get to a later position
* for reading. An audio input stream may support marks. When you set a mark,
* the current position is remembered so that you can return to it later.
* <p>
* The <code>AudioSystem</code> class includes many methods that manipulate
* <code>AudioInputStream</code> objects.
* For example, the methods let you:
* <ul>
* <li> obtain an
* audio input stream from an external audio file, stream, or URL
* <li> write an external file from an audio input stream
* <li> convert an audio input stream to a different audio format
* </ul>
*
* @author David Rivas
* @author Kara Kytle
* @author Florian Bomers
*
* @see AudioSystem
* @see Clip#open(AudioInputStream) Clip.open(AudioInputStream)
* @since 1.3
*/
public class AudioInputStream extends InputStream {
/**
* The <code>InputStream</code> from which this <code>AudioInputStream</code>
* object was constructed.
*/
private InputStream stream;
/**
* The format of the audio data contained in the stream.
*/
protected AudioFormat format;
/**
* This stream's length, in sample frames.
*/
protected long frameLength;
/**
* The size of each frame, in bytes.
*/
protected int frameSize;
/**
* The current position in this stream, in sample frames (zero-based).
*/
protected long framePos;
/**
* The position where a mark was set.
*/
private long markpos;
/**
* When the underlying stream could only return
* a non-integral number of frames, store
* the remainder in a temporary buffer
*/
private byte[] pushBackBuffer = null;
/**
* number of valid bytes in the pushBackBuffer
*/
private int pushBackLen = 0;
/**
* MarkBuffer at mark position
*/
private byte[] markPushBackBuffer = null;
/**
* number of valid bytes in the markPushBackBuffer
*/
private int markPushBackLen = 0;
/**
* Constructs an audio input stream that has the requested format and length in sample frames,
* using audio data from the specified input stream.
* @param stream the stream on which this <code>AudioInputStream</code>
* object is based
* @param format the format of this stream's audio data
* @param length the length in sample frames of the data in this stream
*/
public AudioInputStream(InputStream stream, AudioFormat format, long length) {
super();
this.format = format;
this.frameLength = length;
this.frameSize = format.getFrameSize();
// any frameSize that is not well-defined will
// cause that this stream will be read in bytes
if( this.frameSize == AudioSystem.NOT_SPECIFIED || frameSize <= 0) {
this.frameSize = 1;
}
this.stream = stream;
framePos = 0;
markpos = 0;
}
/**
* Constructs an audio input stream that reads its data from the target
* data line indicated. The format of the stream is the same as that of
* the target data line, and the length is AudioSystem#NOT_SPECIFIED.
* @param line the target data line from which this stream obtains its data.
* @see AudioSystem#NOT_SPECIFIED
*/
public AudioInputStream(TargetDataLine line) {
TargetDataLineInputStream tstream = new TargetDataLineInputStream(line);
format = line.getFormat();
frameLength = AudioSystem.NOT_SPECIFIED;
frameSize = format.getFrameSize();
if( frameSize == AudioSystem.NOT_SPECIFIED || frameSize <= 0) {
frameSize = 1;
}
this.stream = tstream;
framePos = 0;
markpos = 0;
}
/**
* Obtains the audio format of the sound data in this audio input stream.
* @return an audio format object describing this stream's format
*/
public AudioFormat getFormat() {
return format;
}
/**
* Obtains the length of the stream, expressed in sample frames rather than bytes.
* @return the length in sample frames
*/
public long getFrameLength() {
return frameLength;
}
/**
* Reads the next byte of data from the audio input stream. The audio input
* stream's frame size must be one byte, or an <code>IOException</code>
* will be thrown.
*
* @return the next byte of data, or -1 if the end of the stream is reached
* @throws IOException if an input or output error occurs
* @see #read(byte[], int, int)
* @see #read(byte[])
* @see #available
* <p>
*/
public int read() throws IOException {
if( frameSize != 1 ) {
throw new IOException("cannot read a single byte if frame size > 1");
}
byte[] data = new byte[1];
int temp = read(data);
if (temp <= 0) {
// we have a weird situation if read(byte[]) returns 0!
return -1;
}
return data[0] & 0xFF;
}
/**
* Reads some number of bytes from the audio input stream and stores them into
* the buffer array <code>b</code>. The number of bytes actually read is
* returned as an integer. This method blocks until input data is
* available, the end of the stream is detected, or an exception is thrown.
* <p>This method will always read an integral number of frames.
* If the length of the array is not an integral number
* of frames, a maximum of <code>b.length - (b.length % frameSize)
* </code> bytes will be read.
*
* @param b the buffer into which the data is read
* @return the total number of bytes read into the buffer, or -1 if there
* is no more data because the end of the stream has been reached
* @throws IOException if an input or output error occurs
* @see #read(byte[], int, int)
* @see #read()
* @see #available
*/
public int read(byte[] b) throws IOException {
return read(b,0,b.length);
}
/**
* Reads up to a specified maximum number of bytes of data from the audio
* stream, putting them into the given byte array.
* <p>This method will always read an integral number of frames.
* If <code>len</code> does not specify an integral number
* of frames, a maximum of <code>len - (len % frameSize)
* </code> bytes will be read.
*
* @param b the buffer into which the data is read
* @param off the offset, from the beginning of array <code>b</code>, at which
* the data will be written
* @param len the maximum number of bytes to read
* @return the total number of bytes read into the buffer, or -1 if there
* is no more data because the end of the stream has been reached
* @throws IOException if an input or output error occurs
* @see #read(byte[])
* @see #read()
* @see #skip
* @see #available
*/
public int read(byte[] b, int off, int len) throws IOException {
// make sure we don't read fractions of a frame.
if( (len%frameSize) != 0 ) {
len -= (len%frameSize);
if (len == 0) {
return 0;
}
}
if( frameLength != AudioSystem.NOT_SPECIFIED ) {
if( framePos >= frameLength ) {
return -1;
} else {
// don't try to read beyond our own set length in frames
if( (len/frameSize) > (frameLength-framePos) ) {
len = (int) (frameLength-framePos) * frameSize;
}
}
}
int bytesRead = 0;
int thisOff = off;
// if we've bytes left from last call to read(),
// use them first
if (pushBackLen > 0 && len >= pushBackLen) {
System.arraycopy(pushBackBuffer, 0,
b, off, pushBackLen);
thisOff += pushBackLen;
len -= pushBackLen;
bytesRead += pushBackLen;
pushBackLen = 0;
}
int thisBytesRead = stream.read(b, thisOff, len);
if (thisBytesRead == -1) {
return -1;
}
if (thisBytesRead > 0) {
bytesRead += thisBytesRead;
}
if (bytesRead > 0) {
pushBackLen = bytesRead % frameSize;
if (pushBackLen > 0) {
// copy everything we got from the beginning of the frame
// to our pushback buffer
if (pushBackBuffer == null) {
pushBackBuffer = new byte[frameSize];
}
System.arraycopy(b, off + bytesRead - pushBackLen,
pushBackBuffer, 0, pushBackLen);
bytesRead -= pushBackLen;
}
// make sure to update our framePos
framePos += bytesRead/frameSize;
}
return bytesRead;
}
/**
* Skips over and discards a specified number of bytes from this
* audio input stream.
* @param n the requested number of bytes to be skipped
* @return the actual number of bytes skipped
* @throws IOException if an input or output error occurs
* @see #read
* @see #available
*/
public long skip(long n) throws IOException {
// make sure not to skip fractional frames
if( (n%frameSize) != 0 ) {
n -= (n%frameSize);
}
if( frameLength != AudioSystem.NOT_SPECIFIED ) {
// don't skip more than our set length in frames.
if( (n/frameSize) > (frameLength-framePos) ) {
n = (frameLength-framePos) * frameSize;
}
}
long temp = stream.skip(n);
// if no error, update our position.
if( temp%frameSize != 0 ) {
// Throw an IOException if we've skipped a fractional number of frames
throw new IOException("Could not skip an integer number of frames.");
}
if( temp >= 0 ) {
framePos += temp/frameSize;
}
return temp;
}
/**
* Returns the maximum number of bytes that can be read (or skipped over) from this
* audio input stream without blocking. This limit applies only to the next invocation of
* a <code>read</code> or <code>skip</code> method for this audio input stream; the limit
* can vary each time these methods are invoked.
* Depending on the underlying stream,an IOException may be thrown if this
* stream is closed.
* @return the number of bytes that can be read from this audio input stream without blocking
* @throws IOException if an input or output error occurs
* @see #read(byte[], int, int)
* @see #read(byte[])
* @see #read()
* @see #skip
*/
public int available() throws IOException {
int temp = stream.available();
// don't return greater than our set length in frames
if( (frameLength != AudioSystem.NOT_SPECIFIED) && ( (temp/frameSize) > (frameLength-framePos)) ) {
return (int) (frameLength-framePos) * frameSize;
} else {
return temp;
}
}
/**
* Closes this audio input stream and releases any system resources associated
* with the stream.
* @throws IOException if an input or output error occurs
*/
public void close() throws IOException {
stream.close();
}
/**
* Marks the current position in this audio input stream.
* @param readlimit the maximum number of bytes that can be read before
* the mark position becomes invalid.
* @see #reset
* @see #markSupported
*/
public void mark(int readlimit) {
stream.mark(readlimit);
if (markSupported()) {
markpos = framePos;
// remember the pushback buffer
markPushBackLen = pushBackLen;
if (markPushBackLen > 0) {
if (markPushBackBuffer == null) {
markPushBackBuffer = new byte[frameSize];
}
System.arraycopy(pushBackBuffer, 0, markPushBackBuffer, 0, markPushBackLen);
}
}
}
/**
* Repositions this audio input stream to the position it had at the time its
* <code>mark</code> method was last invoked.
* @throws IOException if an input or output error occurs.
* @see #mark
* @see #markSupported
*/
public void reset() throws IOException {
stream.reset();
framePos = markpos;
// re-create the pushback buffer
pushBackLen = markPushBackLen;
if (pushBackLen > 0) {
if (pushBackBuffer == null) {
pushBackBuffer = new byte[frameSize - 1];
}
System.arraycopy(markPushBackBuffer, 0, pushBackBuffer, 0, pushBackLen);
}
}
/**
* Tests whether this audio input stream supports the <code>mark</code> and
* <code>reset</code> methods.
* @return <code>true</code> if this stream supports the <code>mark</code>
* and <code>reset</code> methods; <code>false</code> otherwise
* @see #mark
* @see #reset
*/
public boolean markSupported() {
return stream.markSupported();
}
/**
* Private inner class that makes a TargetDataLine look like an InputStream.
*/
private class TargetDataLineInputStream extends InputStream {
/**
* The TargetDataLine on which this TargetDataLineInputStream is based.
*/
TargetDataLine line;
TargetDataLineInputStream(TargetDataLine line) {
super();
this.line = line;
}
public int available() throws IOException {
return line.available();
}
//$$fb 2001-07-16: added this method to correctly close the underlying TargetDataLine.
// fixes bug 4479984
public void close() throws IOException {
// the line needs to be flushed and stopped to avoid a dead lock...
// Probably related to bugs 4417527, 4334868, 4383457
if (line.isActive()) {
line.flush();
line.stop();
}
line.close();
}
public int read() throws IOException {
byte[] b = new byte[1];
int value = read(b, 0, 1);
if (value == -1) {
return -1;
}
value = (int)b[0];
if (line.getFormat().getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)) {
value += 128;
}
return value;
}
public int read(byte[] b, int off, int len) throws IOException {
try {
return line.read(b, off, len);
} catch (IllegalArgumentException e) {
throw new IOException(e.getMessage());
}
}
}
}

View File

@@ -0,0 +1,236 @@
/*
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
import java.security.BasicPermission;
/**
* The <code>AudioPermission</code> class represents access rights to the audio
* system resources. An <code>AudioPermission</code> contains a target name
* but no actions list; you either have the named permission or you don't.
* <p>
* The target name is the name of the audio permission (see the table below).
* The names follow the hierarchical property-naming convention. Also, an asterisk
* can be used to represent all the audio permissions.
* <p>
* The following table lists the possible <code>AudioPermission</code> target names.
* For each name, the table provides a description of exactly what that permission
* allows, as well as a discussion of the risks of granting code the permission.
* <p>
*
* <table border=1 cellpadding=5 summary="permission target name, what the permission allows, and associated risks">
* <tr>
* <th>Permission Target Name</th>
* <th>What the Permission Allows</th>
* <th>Risks of Allowing this Permission</th>
* </tr>
*
* <tr>
* <td>play</td>
* <td>Audio playback through the audio device or devices on the system.
* Allows the application to obtain and manipulate lines and mixers for
* audio playback (rendering).</td>
* <td>In some cases use of this permission may affect other
* applications because the audio from one line may be mixed with other audio
* being played on the system, or because manipulation of a mixer affects the
* audio for all lines using that mixer.</td>
*</tr>
*
* <tr>
* <td>record</td>
* <td>Audio recording through the audio device or devices on the system.
* Allows the application to obtain and manipulate lines and mixers for
* audio recording (capture).</td>
* <td>In some cases use of this permission may affect other
* applications because manipulation of a mixer affects the audio for all lines
* using that mixer.
* This permission can enable an applet or application to eavesdrop on a user.</td>
*</tr>
*</table>
*<p>
*
* @author Kara Kytle
* @since 1.3
*/
/*
* (OLD PERMISSIONS TAKEN OUT FOR 1.2 BETA)
*
* <tr>
* <td>playback device access</td>
* <td>Direct access to the audio playback device(s), including configuration of the
* playback format, volume, and balance, explicit opening and closing of the device,
* etc.</td>
* <td>Changes the properties of a shared system device and therefore
* can affect other applications.</td>
* </tr>
*
* <tr>
* <td>playback device override</td>
* <td>Manipulation of the audio playback device(s) in a way that directly conflicts
* with use by other applications. This includes closing the device while it is in
* use by another application, changing the device format while another application
* is using it, etc. </td>
* <td>Changes the properties of a shared system device and therefore
* can affect other applications.</td>
* </tr>
*
* <tr>
* <td>record device access</td>
* <td>Direct access to the audio recording device(s), including configuration of the
* the record format, volume, and balance, explicit opening and closing of the device,
* etc.</td>
* <td>Changes the properties of a shared system device and therefore
* can affect other applications.</td>
* </tr>
*
* <tr>
* <td>record device override</td>
* <td>Manipulation of the audio recording device(s) in a way that directly conflicts
* with use by other applications. This includes closing the device while it is in
* use by another application, changing the device format while another application
* is using it, etc. </td>
* <td>Changes the properties of a shared system device and therefore
* can affect other applications.</td>
* </tr>
*
* </table>
*<p>
*
* @author Kara Kytle
* @since 1.3
*/
/*
* The <code>AudioPermission</code> class represents access rights to the audio
* system resources. An <code>AudioPermission</code> contains a target name
* but no actions list; you either have the named permission or you don't.
* <p>
* The target name is the name of the audio permission (see the table below).
* The names follow the hierarchical property-naming convention. Also, an asterisk
* can be used to represent all the audio permissions.
* <p>
* The following table lists all the possible AudioPermission target names.
* For each name, the table provides a description of exactly what that permission
* allows, as well as a discussion of the risks of granting code the permission.
* <p>
*
* <table border=1 cellpadding=5>
* <tr>
* <th>Permission Target Name</th>
* <th>What the Permission Allows</th>
* <th>Risks of Allowing this Permission</th>
* </tr>
*
* <tr>
* <td>play</td>
* <td>Audio playback through the audio device or devices on the system.</td>
* <td>Allows the application to use a system device. Can affect other applications,
* because the result will be mixed with other audio being played on the system.</td>
*</tr>
*
* <tr>
* <td>record</td>
* <td>Recording audio from the audio device or devices on the system,
* commonly through a microphone.</td>
* <td>Can enable an applet or application to eavesdrop on a user.</td>
* </tr>
*
* <tr>
* <td>playback device access</td>
* <td>Direct access to the audio playback device(s), including configuration of the
* playback format, volume, and balance, explicit opening and closing of the device,
* etc.</td>
* <td>Changes the properties of a shared system device and therefore
* can affect other applications.</td>
* </tr>
*
* <tr>
* <td>playback device override</td>
* <td>Manipulation of the audio playback device(s) in a way that directly conflicts
* with use by other applications. This includes closing the device while it is in
* use by another application, changing the device format while another application
* is using it, etc. </td>
* <td>Changes the properties of a shared system device and therefore
* can affect other applications.</td>
* </tr>
*
* <tr>
* <td>record device access</td>
* <td>Direct access to the audio recording device(s), including configuration of the
* the record format, volume, and balance, explicit opening and closing of the device,
* etc.</td>
* <td>Changes the properties of a shared system device and therefore
* can affect other applications.</td>
* </tr>
*
* <tr>
* <td>record device override</td>
* <td>Manipulation of the audio recording device(s) in a way that directly conflicts
* with use by other applications. This includes closing the device while it is in
* use by another application, changing the device format while another application
* is using it, etc. </td>
* <td>Changes the properties of a shared system device and therefore
* can affect other applications.</td>
* </tr>
*
* </table>
*<p>
*
* @author Kara Kytle
*/
public class AudioPermission extends BasicPermission {
/**
* Creates a new <code>AudioPermission</code> object that has the specified
* symbolic name, such as "play" or "record". An asterisk can be used to indicate
* all audio permissions.
* @param name the name of the new <code>AudioPermission</code>
*
* @throws NullPointerException if <code>name</code> is <code>null</code>.
* @throws IllegalArgumentException if <code>name</code> is empty.
*/
public AudioPermission(String name) {
super(name);
}
/**
* Creates a new <code>AudioPermission</code> object that has the specified
* symbolic name, such as "play" or "record". The <code>actions</code>
* parameter is currently unused and should be <code>null</code>.
* @param name the name of the new <code>AudioPermission</code>
* @param actions (unused; should be <code>null</code>)
*
* @throws NullPointerException if <code>name</code> is <code>null</code>.
* @throws IllegalArgumentException if <code>name</code> is empty.
*/
public AudioPermission(String name, String actions) {
super(name, actions);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,193 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* A <code>BooleanControl</code> provides the ability to switch between
* two possible settings that affect a line's audio. The settings are boolean
* values (<code>true</code> and <code>false</code>). A graphical user interface
* might represent the control by a two-state button, an on/off switch, two
* mutually exclusive buttons, or a checkbox (among other possibilities).
* For example, depressing a button might activate a
* <code>{@link BooleanControl.Type#MUTE MUTE}</code> control to silence
* the line's audio.
* <p>
* As with other <code>{@link Control}</code> subclasses, a method is
* provided that returns string labels for the values, suitable for
* display in the user interface.
*
* @author Kara Kytle
* @since 1.3
*/
public abstract class BooleanControl extends Control {
// INSTANCE VARIABLES
/**
* The <code>true</code> state label, such as "true" or "on."
*/
private final String trueStateLabel;
/**
* The <code>false</code> state label, such as "false" or "off."
*/
private final String falseStateLabel;
/**
* The current value.
*/
private boolean value;
// CONSTRUCTORS
/**
* Constructs a new boolean control object with the given parameters.
*
* @param type the type of control represented this float control object
* @param initialValue the initial control value
* @param trueStateLabel the label for the state represented by <code>true</code>,
* such as "true" or "on."
* @param falseStateLabel the label for the state represented by <code>false</code>,
* such as "false" or "off."
*/
protected BooleanControl(Type type, boolean initialValue, String trueStateLabel, String falseStateLabel) {
super(type);
this.value = initialValue;
this.trueStateLabel = trueStateLabel;
this.falseStateLabel = falseStateLabel;
}
/**
* Constructs a new boolean control object with the given parameters.
* The labels for the <code>true</code> and <code>false</code> states
* default to "true" and "false."
*
* @param type the type of control represented by this float control object
* @param initialValue the initial control value
*/
protected BooleanControl(Type type, boolean initialValue) {
this(type, initialValue, "true", "false");
}
// METHODS
/**
* Sets the current value for the control. The default
* implementation simply sets the value as indicated.
* Some controls require that their line be open before they can be affected
* by setting a value.
* @param value desired new value.
*/
public void setValue(boolean value) {
this.value = value;
}
/**
* Obtains this control's current value.
* @return current value.
*/
public boolean getValue() {
return value;
}
/**
* Obtains the label for the specified state.
* @param state the state whose label will be returned
* @return the label for the specified state, such as "true" or "on"
* for <code>true</code>, or "false" or "off" for <code>false</code>.
*/
public String getStateLabel(boolean state) {
return ((state == true) ? trueStateLabel : falseStateLabel);
}
// ABSTRACT METHOD IMPLEMENTATIONS: CONTROL
/**
* Provides a string representation of the control
* @return a string description
*/
public String toString() {
return new String(super.toString() + " with current value: " + getStateLabel(getValue()));
}
// INNER CLASSES
/**
* An instance of the <code>BooleanControl.Type</code> class identifies one kind of
* boolean control. Static instances are provided for the
* common types.
*
* @author Kara Kytle
* @since 1.3
*/
public static class Type extends Control.Type {
// TYPE DEFINES
/**
* Represents a control for the mute status of a line.
* Note that mute status does not affect gain.
*/
public static final Type MUTE = new Type("Mute");
/**
* Represents a control for whether reverberation is applied
* to a line. Note that the status of this control not affect
* the reverberation settings for a line, but does affect whether
* these settings are used.
*/
public static final Type APPLY_REVERB = new Type("Apply Reverb");
// CONSTRUCTOR
/**
* Constructs a new boolean control type.
* @param name the name of the new boolean control type
*/
protected Type(String name) {
super(name);
}
} // class Type
}

View File

@@ -0,0 +1,223 @@
/*
* Copyright (c) 1999, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
import java.io.InputStream;
import java.io.IOException;
/**
* The <code>Clip</code> interface represents a special kind of data line whose
* audio data can be loaded prior to playback, instead of being streamed in
* real time.
* <p>
* Because the data is pre-loaded and has a known length, you can set a clip
* to start playing at any position in its audio data. You can also create a
* loop, so that when the clip is played it will cycle repeatedly. Loops are
* specified with a starting and ending sample frame, along with the number of
* times that the loop should be played.
* <p>
* Clips may be obtained from a <code>{@link Mixer}</code> that supports lines
* of this type. Data is loaded into a clip when it is opened.
* <p>
* Playback of an audio clip may be started and stopped using the <code>start</code>
* and <code>stop</code> methods. These methods do not reset the media position;
* <code>start</code> causes playback to continue from the position where playback
* was last stopped. To restart playback from the beginning of the clip's audio
* data, simply follow the invocation of <code>{@link DataLine#stop stop}</code>
* with setFramePosition(0), which rewinds the media to the beginning
* of the clip.
*
* @author Kara Kytle
* @since 1.3
*/
public interface Clip extends DataLine {
/**
* A value indicating that looping should continue indefinitely rather than
* complete after a specific number of loops.
* @see #loop
*/
public static final int LOOP_CONTINUOUSLY = -1;
/**
* Opens the clip, meaning that it should acquire any required
* system resources and become operational. The clip is opened
* with the format and audio data indicated.
* If this operation succeeds, the line is marked as open and an
* <code>{@link LineEvent.Type#OPEN OPEN}</code> event is dispatched
* to the line's listeners.
* <p>
* Invoking this method on a line which is already open is illegal
* and may result in an IllegalStateException.
* <p>
* Note that some lines, once closed, cannot be reopened. Attempts
* to reopen such a line will always result in a
* <code>{@link LineUnavailableException}</code>.
*
* @param format the format of the supplied audio data
* @param data a byte array containing audio data to load into the clip
* @param offset the point at which to start copying, expressed in
* <em>bytes</em> from the beginning of the array
* @param bufferSize the number of <em>bytes</em>
* of data to load into the clip from the array.
* @throws LineUnavailableException if the line cannot be
* opened due to resource restrictions
* @throws IllegalArgumentException if the buffer size does not represent
* an integral number of sample frames,
* or if <code>format</code> is not fully specified or invalid
* @throws IllegalStateException if the line is already open
* @throws SecurityException if the line cannot be
* opened due to security restrictions
*
* @see #close
* @see #isOpen
* @see LineListener
*/
public void open(AudioFormat format, byte[] data, int offset, int bufferSize) throws LineUnavailableException;
/**
* Opens the clip with the format and audio data present in the provided audio
* input stream. Opening a clip means that it should acquire any required
* system resources and become operational. If this operation
* input stream. If this operation
* succeeds, the line is marked open and an
* <code>{@link LineEvent.Type#OPEN OPEN}</code> event is dispatched
* to the line's listeners.
* <p>
* Invoking this method on a line which is already open is illegal
* and may result in an IllegalStateException.
* <p>
* Note that some lines, once closed, cannot be reopened. Attempts
* to reopen such a line will always result in a
* <code>{@link LineUnavailableException}</code>.
*
* @param stream an audio input stream from which audio data will be read into
* the clip
* @throws LineUnavailableException if the line cannot be
* opened due to resource restrictions
* @throws IOException if an I/O exception occurs during reading of
* the stream
* @throws IllegalArgumentException if the stream's audio format
* is not fully specified or invalid
* @throws IllegalStateException if the line is already open
* @throws SecurityException if the line cannot be
* opened due to security restrictions
*
* @see #close
* @see #isOpen
* @see LineListener
*/
public void open(AudioInputStream stream) throws LineUnavailableException, IOException;
/**
* Obtains the media length in sample frames.
* @return the media length, expressed in sample frames,
* or <code>AudioSystem.NOT_SPECIFIED</code> if the line is not open.
* @see AudioSystem#NOT_SPECIFIED
*/
public int getFrameLength();
/**
* Obtains the media duration in microseconds
* @return the media duration, expressed in microseconds,
* or <code>AudioSystem.NOT_SPECIFIED</code> if the line is not open.
* @see AudioSystem#NOT_SPECIFIED
*/
public long getMicrosecondLength();
/**
* Sets the media position in sample frames. The position is zero-based;
* the first frame is frame number zero. When the clip begins playing the
* next time, it will start by playing the frame at this position.
* <p>
* To obtain the current position in sample frames, use the
* <code>{@link DataLine#getFramePosition getFramePosition}</code>
* method of <code>DataLine</code>.
*
* @param frames the desired new media position, expressed in sample frames
*/
public void setFramePosition(int frames);
/**
* Sets the media position in microseconds. When the clip begins playing the
* next time, it will start at this position.
* The level of precision is not guaranteed. For example, an implementation
* might calculate the microsecond position from the current frame position
* and the audio sample frame rate. The precision in microseconds would
* then be limited to the number of microseconds per sample frame.
* <p>
* To obtain the current position in microseconds, use the
* <code>{@link DataLine#getMicrosecondPosition getMicrosecondPosition}</code>
* method of <code>DataLine</code>.
*
* @param microseconds the desired new media position, expressed in microseconds
*/
public void setMicrosecondPosition(long microseconds);
/**
* Sets the first and last sample frames that will be played in
* the loop. The ending point must be greater than
* or equal to the starting point, and both must fall within the
* the size of the loaded media. A value of 0 for the starting
* point means the beginning of the loaded media. Similarly, a value of -1
* for the ending point indicates the last frame of the media.
* @param start the loop's starting position, in sample frames (zero-based)
* @param end the loop's ending position, in sample frames (zero-based), or
* -1 to indicate the final frame
* @throws IllegalArgumentException if the requested
* loop points cannot be set, usually because one or both falls outside
* the media's duration or because the ending point is
* before the starting point
*/
public void setLoopPoints(int start, int end);
/**
* Starts looping playback from the current position. Playback will
* continue to the loop's end point, then loop back to the loop start point
* <code>count</code> times, and finally continue playback to the end of
* the clip.
* <p>
* If the current position when this method is invoked is greater than the
* loop end point, playback simply continues to the
* end of the clip without looping.
* <p>
* A <code>count</code> value of 0 indicates that any current looping should
* cease and playback should continue to the end of the clip. The behavior
* is undefined when this method is invoked with any other value during a
* loop operation.
* <p>
* If playback is stopped during looping, the current loop status is
* cleared; the behavior of subsequent loop and start requests is not
* affected by an interrupted loop operation.
*
* @param count the number of times playback should loop back from the
* loop's end position to the loop's start position, or
* <code>{@link #LOOP_CONTINUOUSLY}</code> to indicate that looping should
* continue until interrupted
*/
public void loop(int count);
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright (c) 1999, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* A <code>CompoundControl</code>, such as a graphic equalizer, provides control
* over two or more related properties, each of which is itself represented as
* a <code>Control</code>.
*
* @author Kara Kytle
* @since 1.3
*/
public abstract class CompoundControl extends Control {
// TYPE DEFINES
// INSTANCE VARIABLES
/**
* The set of member controls.
*/
private Control[] controls;
// CONSTRUCTORS
/**
* Constructs a new compound control object with the given parameters.
*
* @param type the type of control represented this compound control object
* @param memberControls the set of member controls
*/
protected CompoundControl(Type type, Control[] memberControls) {
super(type);
this.controls = memberControls;
}
// METHODS
/**
* Returns the set of member controls that comprise the compound control.
* @return the set of member controls.
*/
public Control[] getMemberControls() {
Control[] localArray = new Control[controls.length];
for (int i = 0; i < controls.length; i++) {
localArray[i] = controls[i];
}
return localArray;
}
// ABSTRACT METHOD IMPLEMENTATIONS: CONTROL
/**
* Provides a string representation of the control
* @return a string description
*/
public String toString() {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < controls.length; i++) {
if (i != 0) {
buf.append(", ");
if ((i + 1) == controls.length) {
buf.append("and ");
}
}
buf.append(controls[i].getType());
}
return new String(getType() + " Control containing " + buf + " Controls.");
}
// INNER CLASSES
/**
* An instance of the <code>CompoundControl.Type</code> inner class identifies one kind of
* compound control. Static instances are provided for the
* common types.
*
* @author Kara Kytle
* @since 1.3
*/
public static class Type extends Control.Type {
// TYPE DEFINES
// CONSTRUCTOR
/**
* Constructs a new compound control type.
* @param name the name of the new compound control type
*/
protected Type(String name) {
super(name);
}
} // class Type
} // class CompoundControl

View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* {@link Line Lines} often have a set of controls, such as gain and pan, that affect
* the audio signal passing through the line. Java Sound's <code>Line</code> objects
* let you obtain a particular control object by passing its class as the
* argument to a {@link Line#getControl(Control.Type) getControl} method.
* <p>
* Because the various types of controls have different purposes and features,
* all of their functionality is accessed from the subclasses that define
* each kind of control.
*
* @author Kara Kytle
*
* @see Line#getControls
* @see Line#isControlSupported
* @since 1.3
*/
public abstract class Control {
// INSTANCE VARIABLES
/**
* The control type.
*/
private final Type type;
// CONSTRUCTORS
/**
* Constructs a Control with the specified type.
* @param type the kind of control desired
*/
protected Control(Type type) {
this.type = type;
}
// METHODS
/**
* Obtains the control's type.
* @return the control's type.
*/
public Type getType() {
return type;
}
// ABSTRACT METHODS
/**
* Obtains a String describing the control type and its current state.
* @return a String representation of the Control.
*/
public String toString() {
return new String(getType() + " Control");
}
/**
* An instance of the <code>Type</code> class represents the type of
* the control. Static instances are provided for the
* common types.
*/
public static class Type {
// CONTROL TYPE DEFINES
// INSTANCE VARIABLES
/**
* Type name.
*/
private String name;
// CONSTRUCTOR
/**
* Constructs a new control type with the name specified.
* The name should be a descriptive string appropriate for
* labelling the control in an application, such as "Gain" or "Balance."
* @param name the name of the new control type.
*/
protected Type(String name) {
this.name = name;
}
// METHODS
/**
* Finalizes the equals method
*/
public final boolean equals(Object obj) {
return super.equals(obj);
}
/**
* Finalizes the hashCode method
*/
public final int hashCode() {
return super.hashCode();
}
/**
* Provides the <code>String</code> representation of the control type. This <code>String</code> is
* the same name that was passed to the constructor.
*
* @return the control type name
*/
public final String toString() {
return name;
}
} // class Type
} // class Control

View File

@@ -0,0 +1,494 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
import java.util.Arrays;
/**
* <code>DataLine</code> adds media-related functionality to its
* superinterface, <code>{@link Line}</code>. This functionality includes
* transport-control methods that start, stop, drain, and flush
* the audio data that passes through the line. A data line can also
* report the current position, volume, and audio format of the media.
* Data lines are used for output of audio by means of the
* subinterfaces <code>{@link SourceDataLine}</code> or
* <code>{@link Clip}</code>, which allow an application program to write data. Similarly,
* audio input is handled by the subinterface <code>{@link TargetDataLine}</code>,
* which allows data to be read.
* <p>
* A data line has an internal buffer in which
* the incoming or outgoing audio data is queued. The
* <code>{@link #drain()}</code> method blocks until this internal buffer
* becomes empty, usually because all queued data has been processed. The
* <code>{@link #flush()}</code> method discards any available queued data
* from the internal buffer.
* <p>
* A data line produces <code>{@link LineEvent.Type#START START}</code> and
* <code>{@link LineEvent.Type#STOP STOP}</code> events whenever
* it begins or ceases active presentation or capture of data. These events
* can be generated in response to specific requests, or as a result of
* less direct state changes. For example, if <code>{@link #start()}</code> is called
* on an inactive data line, and data is available for capture or playback, a
* <code>START</code> event will be generated shortly, when data playback
* or capture actually begins. Or, if the flow of data to an active data
* line is constricted so that a gap occurs in the presentation of data,
* a <code>STOP</code> event is generated.
* <p>
* Mixers often support synchronized control of multiple data lines.
* Synchronization can be established through the Mixer interface's
* <code>{@link Mixer#synchronize synchronize}</code> method.
* See the description of the <code>{@link Mixer Mixer}</code> interface
* for a more complete description.
*
* @author Kara Kytle
* @see LineEvent
* @since 1.3
*/
public interface DataLine extends Line {
/**
* Drains queued data from the line by continuing data I/O until the
* data line's internal buffer has been emptied.
* This method blocks until the draining is complete. Because this is a
* blocking method, it should be used with care. If <code>drain()</code>
* is invoked on a stopped line that has data in its queue, the method will
* block until the line is running and the data queue becomes empty. If
* <code>drain()</code> is invoked by one thread, and another continues to
* fill the data queue, the operation will not complete.
* This method always returns when the data line is closed.
*
* @see #flush()
*/
public void drain();
/**
* Flushes queued data from the line. The flushed data is discarded.
* In some cases, not all queued data can be discarded. For example, a
* mixer can flush data from the buffer for a specific input line, but any
* unplayed data already in the output buffer (the result of the mix) will
* still be played. You can invoke this method after pausing a line (the
* normal case) if you want to skip the "stale" data when you restart
* playback or capture. (It is legal to flush a line that is not stopped,
* but doing so on an active line is likely to cause a discontinuity in the
* data, resulting in a perceptible click.)
*
* @see #stop()
* @see #drain()
*/
public void flush();
/**
* Allows a line to engage in data I/O. If invoked on a line
* that is already running, this method does nothing. Unless the data in
* the buffer has been flushed, the line resumes I/O starting
* with the first frame that was unprocessed at the time the line was
* stopped. When audio capture or playback starts, a
* <code>{@link LineEvent.Type#START START}</code> event is generated.
*
* @see #stop()
* @see #isRunning()
* @see LineEvent
*/
public void start();
/**
* Stops the line. A stopped line should cease I/O activity.
* If the line is open and running, however, it should retain the resources required
* to resume activity. A stopped line should retain any audio data in its buffer
* instead of discarding it, so that upon resumption the I/O can continue where it left off,
* if possible. (This doesn't guarantee that there will never be discontinuities beyond the
* current buffer, of course; if the stopped condition continues
* for too long, input or output samples might be dropped.) If desired, the retained data can be
* discarded by invoking the <code>flush</code> method.
* When audio capture or playback stops, a <code>{@link LineEvent.Type#STOP STOP}</code> event is generated.
*
* @see #start()
* @see #isRunning()
* @see #flush()
* @see LineEvent
*/
public void stop();
/**
* Indicates whether the line is running. The default is <code>false</code>.
* An open line begins running when the first data is presented in response to an
* invocation of the <code>start</code> method, and continues
* until presentation ceases in response to a call to <code>stop</code> or
* because playback completes.
* @return <code>true</code> if the line is running, otherwise <code>false</code>
* @see #start()
* @see #stop()
*/
public boolean isRunning();
/**
* Indicates whether the line is engaging in active I/O (such as playback
* or capture). When an inactive line becomes active, it sends a
* <code>{@link LineEvent.Type#START START}</code> event to its listeners. Similarly, when
* an active line becomes inactive, it sends a
* <code>{@link LineEvent.Type#STOP STOP}</code> event.
* @return <code>true</code> if the line is actively capturing or rendering
* sound, otherwise <code>false</code>
* @see #isOpen
* @see #addLineListener
* @see #removeLineListener
* @see LineEvent
* @see LineListener
*/
public boolean isActive();
/**
* Obtains the current format (encoding, sample rate, number of channels,
* etc.) of the data line's audio data.
*
* <p>If the line is not open and has never been opened, it returns
* the default format. The default format is an implementation
* specific audio format, or, if the <code>DataLine.Info</code>
* object, which was used to retrieve this <code>DataLine</code>,
* specifies at least one fully qualified audio format, the
* last one will be used as the default format. Opening the
* line with a specific audio format (e.g.
* {@link SourceDataLine#open(AudioFormat)}) will override the
* default format.
*
* @return current audio data format
* @see AudioFormat
*/
public AudioFormat getFormat();
/**
* Obtains the maximum number of bytes of data that will fit in the data line's
* internal buffer. For a source data line, this is the size of the buffer to
* which data can be written. For a target data line, it is the size of
* the buffer from which data can be read. Note that
* the units used are bytes, but will always correspond to an integral
* number of sample frames of audio data.
*
* @return the size of the buffer in bytes
*/
public int getBufferSize();
/**
* Obtains the number of bytes of data currently available to the
* application for processing in the data line's internal buffer. For a
* source data line, this is the amount of data that can be written to the
* buffer without blocking. For a target data line, this is the amount of data
* available to be read by the application. For a clip, this value is always
* 0 because the audio data is loaded into the buffer when the clip is opened,
* and persists without modification until the clip is closed.
* <p>
* Note that the units used are bytes, but will always
* correspond to an integral number of sample frames of audio data.
* <p>
* An application is guaranteed that a read or
* write operation of up to the number of bytes returned from
* <code>available()</code> will not block; however, there is no guarantee
* that attempts to read or write more data will block.
*
* @return the amount of data available, in bytes
*/
public int available();
/**
* Obtains the current position in the audio data, in sample frames.
* The frame position measures the number of sample
* frames captured by, or rendered from, the line since it was opened.
* This return value will wrap around after 2^31 frames. It is recommended
* to use <code>getLongFramePosition</code> instead.
*
* @return the number of frames already processed since the line was opened
* @see #getLongFramePosition()
*/
public int getFramePosition();
/**
* Obtains the current position in the audio data, in sample frames.
* The frame position measures the number of sample
* frames captured by, or rendered from, the line since it was opened.
*
* @return the number of frames already processed since the line was opened
* @since 1.5
*/
public long getLongFramePosition();
/**
* Obtains the current position in the audio data, in microseconds.
* The microsecond position measures the time corresponding to the number
* of sample frames captured by, or rendered from, the line since it was opened.
* The level of precision is not guaranteed. For example, an implementation
* might calculate the microsecond position from the current frame position
* and the audio sample frame rate. The precision in microseconds would
* then be limited to the number of microseconds per sample frame.
*
* @return the number of microseconds of data processed since the line was opened
*/
public long getMicrosecondPosition();
/**
* Obtains the current volume level for the line. This level is a measure
* of the signal's current amplitude, and should not be confused with the
* current setting of a gain control. The range is from 0.0 (silence) to
* 1.0 (maximum possible amplitude for the sound waveform). The units
* measure linear amplitude, not decibels.
*
* @return the current amplitude of the signal in this line, or
* <code>{@link AudioSystem#NOT_SPECIFIED}</code>
*/
public float getLevel();
/**
* Besides the class information inherited from its superclass,
* <code>DataLine.Info</code> provides additional information specific to data lines.
* This information includes:
* <ul>
* <li> the audio formats supported by the data line
* <li> the minimum and maximum sizes of its internal buffer
* </ul>
* Because a <code>Line.Info</code> knows the class of the line its describes, a
* <code>DataLine.Info</code> object can describe <code>DataLine</code>
* subinterfaces such as <code>{@link SourceDataLine}</code>,
* <code>{@link TargetDataLine}</code>, and <code>{@link Clip}</code>.
* You can query a mixer for lines of any of these types, passing an appropriate
* instance of <code>DataLine.Info</code> as the argument to a method such as
* <code>{@link Mixer#getLine Mixer.getLine(Line.Info)}</code>.
*
* @see Line.Info
* @author Kara Kytle
* @since 1.3
*/
public static class Info extends Line.Info {
private final AudioFormat[] formats;
private final int minBufferSize;
private final int maxBufferSize;
/**
* Constructs a data line's info object from the specified information,
* which includes a set of supported audio formats and a range for the buffer size.
* This constructor is typically used by mixer implementations
* when returning information about a supported line.
*
* @param lineClass the class of the data line described by the info object
* @param formats set of formats supported
* @param minBufferSize minimum buffer size supported by the data line, in bytes
* @param maxBufferSize maximum buffer size supported by the data line, in bytes
*/
public Info(Class<?> lineClass, AudioFormat[] formats, int minBufferSize, int maxBufferSize) {
super(lineClass);
if (formats == null) {
this.formats = new AudioFormat[0];
} else {
this.formats = Arrays.copyOf(formats, formats.length);
}
this.minBufferSize = minBufferSize;
this.maxBufferSize = maxBufferSize;
}
/**
* Constructs a data line's info object from the specified information,
* which includes a single audio format and a desired buffer size.
* This constructor is typically used by an application to
* describe a desired line.
*
* @param lineClass the class of the data line described by the info object
* @param format desired format
* @param bufferSize desired buffer size in bytes
*/
public Info(Class<?> lineClass, AudioFormat format, int bufferSize) {
super(lineClass);
if (format == null) {
this.formats = new AudioFormat[0];
} else {
this.formats = new AudioFormat[]{format};
}
this.minBufferSize = bufferSize;
this.maxBufferSize = bufferSize;
}
/**
* Constructs a data line's info object from the specified information,
* which includes a single audio format.
* This constructor is typically used by an application to
* describe a desired line.
*
* @param lineClass the class of the data line described by the info object
* @param format desired format
*/
public Info(Class<?> lineClass, AudioFormat format) {
this(lineClass, format, AudioSystem.NOT_SPECIFIED);
}
/**
* Obtains a set of audio formats supported by the data line.
* Note that <code>isFormatSupported(AudioFormat)</code> might return
* <code>true</code> for certain additional formats that are missing from
* the set returned by <code>getFormats()</code>. The reverse is not
* the case: <code>isFormatSupported(AudioFormat)</code> is guaranteed to return
* <code>true</code> for all formats returned by <code>getFormats()</code>.
*
* Some fields in the AudioFormat instances can be set to
* {@link javax.sound.sampled.AudioSystem#NOT_SPECIFIED NOT_SPECIFIED}
* if that field does not apply to the format,
* or if the format supports a wide range of values for that field.
* For example, a multi-channel device supporting up to
* 64 channels, could set the channel field in the
* <code>AudioFormat</code> instances returned by this
* method to <code>NOT_SPECIFIED</code>.
*
* @return a set of supported audio formats.
* @see #isFormatSupported(AudioFormat)
*/
public AudioFormat[] getFormats() {
return Arrays.copyOf(formats, formats.length);
}
/**
* Indicates whether this data line supports a particular audio format.
* The default implementation of this method simply returns <code>true</code> if
* the specified format matches any of the supported formats.
*
* @param format the audio format for which support is queried.
* @return <code>true</code> if the format is supported, otherwise <code>false</code>
* @see #getFormats
* @see AudioFormat#matches
*/
public boolean isFormatSupported(AudioFormat format) {
for (int i = 0; i < formats.length; i++) {
if (format.matches(formats[i])) {
return true;
}
}
return false;
}
/**
* Obtains the minimum buffer size supported by the data line.
* @return minimum buffer size in bytes, or <code>AudioSystem.NOT_SPECIFIED</code>
*/
public int getMinBufferSize() {
return minBufferSize;
}
/**
* Obtains the maximum buffer size supported by the data line.
* @return maximum buffer size in bytes, or <code>AudioSystem.NOT_SPECIFIED</code>
*/
public int getMaxBufferSize() {
return maxBufferSize;
}
/**
* Determines whether the specified info object matches this one.
* To match, the superclass match requirements must be met. In
* addition, this object's minimum buffer size must be at least as
* large as that of the object specified, its maximum buffer size must
* be at most as large as that of the object specified, and all of its
* formats must match formats supported by the object specified.
* @return <code>true</code> if this object matches the one specified,
* otherwise <code>false</code>.
*/
public boolean matches(Line.Info info) {
if (! (super.matches(info)) ) {
return false;
}
Info dataLineInfo = (Info)info;
// treat anything < 0 as NOT_SPECIFIED
// demo code in old Java Sound Demo used a wrong buffer calculation
// that would lead to arbitrary negative values
if ((getMaxBufferSize() >= 0) && (dataLineInfo.getMaxBufferSize() >= 0)) {
if (getMaxBufferSize() > dataLineInfo.getMaxBufferSize()) {
return false;
}
}
if ((getMinBufferSize() >= 0) && (dataLineInfo.getMinBufferSize() >= 0)) {
if (getMinBufferSize() < dataLineInfo.getMinBufferSize()) {
return false;
}
}
AudioFormat[] localFormats = getFormats();
if (localFormats != null) {
for (int i = 0; i < localFormats.length; i++) {
if (! (localFormats[i] == null) ) {
if (! (dataLineInfo.isFormatSupported(localFormats[i])) ) {
return false;
}
}
}
}
return true;
}
/**
* Obtains a textual description of the data line info.
* @return a string description
*/
public String toString() {
StringBuffer buf = new StringBuffer();
if ( (formats.length == 1) && (formats[0] != null) ) {
buf.append(" supporting format " + formats[0]);
} else if (getFormats().length > 1) {
buf.append(" supporting " + getFormats().length + " audio formats");
}
if ( (minBufferSize != AudioSystem.NOT_SPECIFIED) && (maxBufferSize != AudioSystem.NOT_SPECIFIED) ) {
buf.append(", and buffers of " + minBufferSize + " to " + maxBufferSize + " bytes");
} else if ( (minBufferSize != AudioSystem.NOT_SPECIFIED) && (minBufferSize > 0) ) {
buf.append(", and buffers of at least " + minBufferSize + " bytes");
} else if (maxBufferSize != AudioSystem.NOT_SPECIFIED) {
buf.append(", and buffers of up to " + minBufferSize + " bytes");
}
return new String(super.toString() + buf);
}
} // class Info
} // interface DataLine

View File

@@ -0,0 +1,214 @@
/*
* Copyright (c) 1999, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* A <code>EnumControl</code> provides control over a set of
* discrete possible values, each represented by an object. In a
* graphical user interface, such a control might be represented
* by a set of buttons, each of which chooses one value or setting. For
* example, a reverb control might provide several preset reverberation
* settings, instead of providing continuously adjustable parameters
* of the sort that would be represented by <code>{@link FloatControl}</code>
* objects.
* <p>
* Controls that provide a choice between only two settings can often be implemented
* instead as a <code>{@link BooleanControl}</code>, and controls that provide
* a set of values along some quantifiable dimension might be implemented
* instead as a <code>FloatControl</code> with a coarse resolution.
* However, a key feature of <code>EnumControl</code> is that the returned values
* are arbitrary objects, rather than numerical or boolean values. This means that each
* returned object can provide further information. As an example, the settings
* of a <code>{@link EnumControl.Type#REVERB REVERB}</code> control are instances of
* <code>{@link ReverbType}</code> that can be queried for the parameter values
* used for each setting.
*
* @author Kara Kytle
* @since 1.3
*/
public abstract class EnumControl extends Control {
// TYPE DEFINES
// INSTANCE VARIABLES
/**
* The set of possible values.
*/
private Object[] values;
/**
* The current value.
*/
private Object value;
// CONSTRUCTORS
/**
* Constructs a new enumerated control object with the given parameters.
*
* @param type the type of control represented this enumerated control object
* @param values the set of possible values for the control
* @param value the initial control value
*/
protected EnumControl(Type type, Object[] values, Object value) {
super(type);
this.values = values;
this.value = value;
}
// METHODS
/**
* Sets the current value for the control. The default implementation
* simply sets the value as indicated. If the value indicated is not
* supported, an IllegalArgumentException is thrown.
* Some controls require that their line be open before they can be affected
* by setting a value.
* @param value the desired new value
* @throws IllegalArgumentException if the value indicated does not fall
* within the allowable range
*/
public void setValue(Object value) {
if (!isValueSupported(value)) {
throw new IllegalArgumentException("Requested value " + value + " is not supported.");
}
this.value = value;
}
/**
* Obtains this control's current value.
* @return the current value
*/
public Object getValue() {
return value;
}
/**
* Returns the set of possible values for this control.
* @return the set of possible values
*/
public Object[] getValues() {
Object[] localArray = new Object[values.length];
for (int i = 0; i < values.length; i++) {
localArray[i] = values[i];
}
return localArray;
}
/**
* Indicates whether the value specified is supported.
* @param value the value for which support is queried
* @return <code>true</code> if the value is supported,
* otherwise <code>false</code>
*/
private boolean isValueSupported(Object value) {
for (int i = 0; i < values.length; i++) {
//$$fb 2001-07-20: Fix for bug 4400392: setValue() in ReverbControl always throws Exception
//if (values.equals(values[i])) {
if (value.equals(values[i])) {
return true;
}
}
return false;
}
// ABSTRACT METHOD IMPLEMENTATIONS: CONTROL
/**
* Provides a string representation of the control.
* @return a string description
*/
public String toString() {
return new String(getType() + " with current value: " + getValue());
}
// INNER CLASSES
/**
* An instance of the <code>EnumControl.Type</code> inner class identifies one kind of
* enumerated control. Static instances are provided for the
* common types.
*
* @see EnumControl
*
* @author Kara Kytle
* @since 1.3
*/
public static class Type extends Control.Type {
// TYPE DEFINES
/**
* Represents a control over a set of possible reverberation settings.
* Each reverberation setting is described by an instance of the
* {@link ReverbType} class. (To access these settings,
* invoke <code>{@link EnumControl#getValues}</code> on an
* enumerated control of type <code>REVERB</code>.)
*/
public static final Type REVERB = new Type("Reverb");
// CONSTRUCTOR
/**
* Constructs a new enumerated control type.
* @param name the name of the new enumerated control type
*/
protected Type(String name) {
super(name);
}
} // class Type
} // class EnumControl

View File

@@ -0,0 +1,529 @@
/*
* Copyright (c) 1999, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* A <code>FloatControl</code> object provides control over a range of
* floating-point values. Float controls are often
* represented in graphical user interfaces by continuously
* adjustable objects such as sliders or rotary knobs. Concrete subclasses
* of <code>FloatControl</code> implement controls, such as gain and pan, that
* affect a line's audio signal in some way that an application can manipulate.
* The <code>{@link FloatControl.Type}</code>
* inner class provides static instances of types that are used to
* identify some common kinds of float control.
* <p>
* The <code>FloatControl</code> abstract class provides methods to set and get
* the control's current floating-point value. Other methods obtain the possible
* range of values and the control's resolution (the smallest increment between
* returned values). Some float controls allow ramping to a
* new value over a specified period of time. <code>FloatControl</code> also
* includes methods that return string labels for the minimum, maximum, and midpoint
* positions of the control.
*
* @see Line#getControls
* @see Line#isControlSupported
*
* @author David Rivas
* @author Kara Kytle
* @since 1.3
*/
public abstract class FloatControl extends Control {
// INSTANCE VARIABLES
// FINAL VARIABLES
/**
* The minimum supported value.
*/
private float minimum;
/**
* The maximum supported value.
*/
private float maximum;
/**
* The control's precision.
*/
private float precision;
/**
* The smallest time increment in which a value change
* can be effected during a value shift, in microseconds.
*/
private int updatePeriod;
/**
* A label for the units in which the control values are expressed,
* such as "dB" for decibels.
*/
private final String units;
/**
* A label for the minimum value, such as "Left."
*/
private final String minLabel;
/**
* A label for the maximum value, such as "Right."
*/
private final String maxLabel;
/**
* A label for the mid-point value, such as "Center."
*/
private final String midLabel;
// STATE VARIABLES
/**
* The current value.
*/
private float value;
// CONSTRUCTORS
/**
* Constructs a new float control object with the given parameters
*
* @param type the kind of control represented by this float control object
* @param minimum the smallest value permitted for the control
* @param maximum the largest value permitted for the control
* @param precision the resolution or granularity of the control.
* This is the size of the increment between discrete valid values.
* @param updatePeriod the smallest time interval, in microseconds, over which the control
* can change from one discrete value to the next during a {@link #shift(float,float,int) shift}
* @param initialValue the value that the control starts with when constructed
* @param units the label for the units in which the control's values are expressed,
* such as "dB" or "frames per second"
* @param minLabel the label for the minimum value, such as "Left" or "Off"
* @param midLabel the label for the midpoint value, such as "Center" or "Default"
* @param maxLabel the label for the maximum value, such as "Right" or "Full"
*
* @throws IllegalArgumentException if {@code minimum} is greater
* than {@code maximum} or {@code initialValue} does not fall
* within the allowable range
*/
protected FloatControl(Type type, float minimum, float maximum,
float precision, int updatePeriod, float initialValue,
String units, String minLabel, String midLabel, String maxLabel) {
super(type);
if (minimum > maximum) {
throw new IllegalArgumentException("Minimum value " + minimum
+ " exceeds maximum value " + maximum + ".");
}
if (initialValue < minimum) {
throw new IllegalArgumentException("Initial value " + initialValue
+ " smaller than allowable minimum value " + minimum + ".");
}
if (initialValue > maximum) {
throw new IllegalArgumentException("Initial value " + initialValue
+ " exceeds allowable maximum value " + maximum + ".");
}
this.minimum = minimum;
this.maximum = maximum;
this.precision = precision;
this.updatePeriod = updatePeriod;
this.value = initialValue;
this.units = units;
this.minLabel = ( (minLabel == null) ? "" : minLabel);
this.midLabel = ( (midLabel == null) ? "" : midLabel);
this.maxLabel = ( (maxLabel == null) ? "" : maxLabel);
}
/**
* Constructs a new float control object with the given parameters.
* The labels for the minimum, maximum, and mid-point values are set
* to zero-length strings.
*
* @param type the kind of control represented by this float control object
* @param minimum the smallest value permitted for the control
* @param maximum the largest value permitted for the control
* @param precision the resolution or granularity of the control.
* This is the size of the increment between discrete valid values.
* @param updatePeriod the smallest time interval, in microseconds, over which the control
* can change from one discrete value to the next during a {@link #shift(float,float,int) shift}
* @param initialValue the value that the control starts with when constructed
* @param units the label for the units in which the control's values are expressed,
* such as "dB" or "frames per second"
*
* @throws IllegalArgumentException if {@code minimum} is greater
* than {@code maximum} or {@code initialValue} does not fall
* within the allowable range
*/
protected FloatControl(Type type, float minimum, float maximum,
float precision, int updatePeriod, float initialValue, String units) {
this(type, minimum, maximum, precision, updatePeriod,
initialValue, units, "", "", "");
}
// METHODS
/**
* Sets the current value for the control. The default implementation
* simply sets the value as indicated. If the value indicated is greater
* than the maximum value, or smaller than the minimum value, an
* IllegalArgumentException is thrown.
* Some controls require that their line be open before they can be affected
* by setting a value.
* @param newValue desired new value
* @throws IllegalArgumentException if the value indicated does not fall
* within the allowable range
*/
public void setValue(float newValue) {
if (newValue > maximum) {
throw new IllegalArgumentException("Requested value " + newValue + " exceeds allowable maximum value " + maximum + ".");
}
if (newValue < minimum) {
throw new IllegalArgumentException("Requested value " + newValue + " smaller than allowable minimum value " + minimum + ".");
}
value = newValue;
}
/**
* Obtains this control's current value.
* @return the current value
*/
public float getValue() {
return value;
}
/**
* Obtains the maximum value permitted.
* @return the maximum allowable value
*/
public float getMaximum() {
return maximum;
}
/**
* Obtains the minimum value permitted.
* @return the minimum allowable value
*/
public float getMinimum() {
return minimum;
}
/**
* Obtains the label for the units in which the control's values are expressed,
* such as "dB" or "frames per second."
* @return the units label, or a zero-length string if no label
*/
public String getUnits() {
return units;
}
/**
* Obtains the label for the minimum value, such as "Left" or "Off."
* @return the minimum value label, or a zero-length string if no label * has been set
*/
public String getMinLabel() {
return minLabel;
}
/**
* Obtains the label for the mid-point value, such as "Center" or "Default."
* @return the mid-point value label, or a zero-length string if no label * has been set
*/
public String getMidLabel() {
return midLabel;
}
/**
* Obtains the label for the maximum value, such as "Right" or "Full."
* @return the maximum value label, or a zero-length string if no label * has been set
*/
public String getMaxLabel() {
return maxLabel;
}
/**
* Obtains the resolution or granularity of the control, in the units
* that the control measures.
* The precision is the size of the increment between discrete valid values
* for this control, over the set of supported floating-point values.
* @return the control's precision
*/
public float getPrecision() {
return precision;
}
/**
* Obtains the smallest time interval, in microseconds, over which the control's value can
* change during a shift. The update period is the inverse of the frequency with which
* the control updates its value during a shift. If the implementation does not support value shifting over
* time, it should set the control's value to the final value immediately
* and return -1 from this method.
*
* @return update period in microseconds, or -1 if shifting over time is unsupported
* @see #shift
*/
public int getUpdatePeriod() {
return updatePeriod;
}
/**
* Changes the control value from the initial value to the final
* value linearly over the specified time period, specified in microseconds.
* This method returns without blocking; it does not wait for the shift
* to complete. An implementation should complete the operation within the time
* specified. The default implementation simply changes the value
* to the final value immediately.
*
* @param from initial value at the beginning of the shift
* @param to final value after the shift
* @param microseconds maximum duration of the shift in microseconds
*
* @throws IllegalArgumentException if either {@code from} or {@code to}
* value does not fall within the allowable range
*
* @see #getUpdatePeriod
*/
public void shift(float from, float to, int microseconds) {
// test "from" value, "to" value will be tested by setValue()
if (from < minimum) {
throw new IllegalArgumentException("Requested value " + from
+ " smaller than allowable minimum value " + minimum + ".");
}
if (from > maximum) {
throw new IllegalArgumentException("Requested value " + from
+ " exceeds allowable maximum value " + maximum + ".");
}
setValue(to);
}
// ABSTRACT METHOD IMPLEMENTATIONS: CONTROL
/**
* Provides a string representation of the control
* @return a string description
*/
public String toString() {
return new String(getType() + " with current value: " + getValue() + " " + units +
" (range: " + minimum + " - " + maximum + ")");
}
// INNER CLASSES
/**
* An instance of the <code>FloatControl.Type</code> inner class identifies one kind of
* float control. Static instances are provided for the
* common types.
*
* @author Kara Kytle
* @since 1.3
*/
public static class Type extends Control.Type {
// TYPE DEFINES
// GAIN TYPES
/**
* Represents a control for the overall gain on a line.
* <p>
* Gain is a quantity in decibels (dB) that is added to the intrinsic
* decibel level of the audio signal--that is, the level of
* the signal before it is altered by the gain control. A positive
* gain amplifies (boosts) the signal's volume, and a negative gain
* attenuates (cuts) it.
* The gain setting defaults to a value of 0.0 dB, meaning the signal's
* loudness is unaffected. Note that gain measures dB, not amplitude.
* The relationship between a gain in decibels and the corresponding
* linear amplitude multiplier is:
*
*<CENTER><CODE> linearScalar = pow(10.0, gainDB/20.0) </CODE></CENTER>
* <p>
* The <code>FloatControl</code> class has methods to impose a maximum and
* minimum allowable value for gain. However, because an audio signal might
* already be at a high amplitude, the maximum setting does not guarantee
* that the signal will be undistorted when the gain is applied to it (unless
* the maximum is zero or negative). To avoid numeric overflow from excessively
* large gain settings, a gain control can implement
* clipping, meaning that the signal's amplitude will be limited to the maximum
* value representable by its audio format, instead of wrapping around.
* <p>
* These comments apply to gain controls in general, not just master gain controls.
* A line can have more than one gain control. For example, a mixer (which is
* itself a line) might have a master gain control, an auxiliary return control,
* a reverb return control, and, on each of its source lines, an individual aux
* send and reverb send.
*
* @see #AUX_SEND
* @see #AUX_RETURN
* @see #REVERB_SEND
* @see #REVERB_RETURN
* @see #VOLUME
*/
public static final Type MASTER_GAIN = new Type("Master Gain");
/**
* Represents a control for the auxiliary send gain on a line.
*
* @see #MASTER_GAIN
* @see #AUX_RETURN
*/
public static final Type AUX_SEND = new Type("AUX Send");
/**
* Represents a control for the auxiliary return gain on a line.
*
* @see #MASTER_GAIN
* @see #AUX_SEND
*/
public static final Type AUX_RETURN = new Type("AUX Return");
/**
* Represents a control for the pre-reverb gain on a line.
* This control may be used to affect how much
* of a line's signal is directed to a mixer's internal reverberation unit.
*
* @see #MASTER_GAIN
* @see #REVERB_RETURN
* @see EnumControl.Type#REVERB
*/
public static final Type REVERB_SEND = new Type("Reverb Send");
/**
* Represents a control for the post-reverb gain on a line.
* This control may be used to control the relative amplitude
* of the signal returned from an internal reverberation unit.
*
* @see #MASTER_GAIN
* @see #REVERB_SEND
*/
public static final Type REVERB_RETURN = new Type("Reverb Return");
// VOLUME
/**
* Represents a control for the volume on a line.
*/
/*
* $$kk: 08.30.99: ISSUE: what units? linear or dB?
*/
public static final Type VOLUME = new Type("Volume");
// PAN
/**
* Represents a control for the relative pan (left-right positioning)
* of the signal. The signal may be mono; the pan setting affects how
* it is distributed by the mixer in a stereo mix. The valid range of values is -1.0
* (left channel only) to 1.0 (right channel
* only). The default is 0.0 (centered).
*
* @see #BALANCE
*/
public static final Type PAN = new Type("Pan");
// BALANCE
/**
* Represents a control for the relative balance of a stereo signal
* between two stereo speakers. The valid range of values is -1.0 (left channel only) to 1.0 (right channel
* only). The default is 0.0 (centered).
*
* @see #PAN
*/
public static final Type BALANCE = new Type("Balance");
// SAMPLE RATE
/**
* Represents a control that changes the sample rate of audio playback. The net effect
* of changing the sample rate depends on the relationship between
* the media's natural rate and the rate that is set via this control.
* The natural rate is the sample rate that is specified in the data line's
* <code>AudioFormat</code> object. For example, if the natural rate
* of the media is 11025 samples per second and the sample rate is set
* to 22050 samples per second, the media will play back at twice the
* normal speed.
* <p>
* Changing the sample rate with this control does not affect the data line's
* audio format. Also note that whenever you change a sound's sample rate, a
* change in the sound's pitch results. For example, doubling the sample
* rate has the effect of doubling the frequencies in the sound's spectrum,
* which raises the pitch by an octave.
*/
public static final Type SAMPLE_RATE = new Type("Sample Rate");
// CONSTRUCTOR
/**
* Constructs a new float control type.
* @param name the name of the new float control type
*/
protected Type(String name) {
super(name);
}
} // class Type
} // class FloatControl

View File

@@ -0,0 +1,359 @@
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* The <code>Line</code> interface represents a mono or multi-channel
* audio feed. A line is an element of the digital audio
* "pipeline," such as a mixer, an input or output port,
* or a data path into or out of a mixer.
* <p>
* A line can have controls, such as gain, pan, and reverb.
* The controls themselves are instances of classes that extend the
* base <code>{@link Control}</code> class.
* The <code>Line</code> interface provides two accessor methods for
* obtaining the line's controls: <code>{@link #getControls getControls}</code> returns the
* entire set, and <code>{@link #getControl getControl}</code> returns a single control of
* specified type.
* <p>
* Lines exist in various states at different times. When a line opens, it reserves system
* resources for itself, and when it closes, these resources are freed for
* other objects or applications. The <code>{@link #isOpen()}</code> method lets
* you discover whether a line is open or closed.
* An open line need not be processing data, however. Such processing is
* typically initiated by subinterface methods such as
* <code>{@link SourceDataLine#write SourceDataLine.write}</code> and
* <code>{@link TargetDataLine#read TargetDataLine.read}</code>.
*<p>
* You can register an object to receive notifications whenever the line's
* state changes. The object must implement the <code>{@link LineListener}</code>
* interface, which consists of the single method
* <code>{@link LineListener#update update}</code>.
* This method will be invoked when a line opens and closes (and, if it's a
* {@link DataLine}, when it starts and stops).
*<p>
* An object can be registered to listen to multiple lines. The event it
* receives in its <code>update</code> method will specify which line created
* the event, what type of event it was
* (<code>OPEN</code>, <code>CLOSE</code>, <code>START</code>, or <code>STOP</code>),
* and how many sample frames the line had processed at the time the event occurred.
* <p>
* Certain line operations, such as open and close, can generate security
* exceptions if invoked by unprivileged code when the line is a shared audio
* resource.
*
* @author Kara Kytle
*
* @see LineEvent
* @since 1.3
*/
public interface Line extends AutoCloseable {
/**
* Obtains the <code>Line.Info</code> object describing this
* line.
* @return description of the line
*/
public Line.Info getLineInfo();
/**
* Opens the line, indicating that it should acquire any required
* system resources and become operational.
* If this operation
* succeeds, the line is marked as open, and an <code>OPEN</code> event is dispatched
* to the line's listeners.
* <p>
* Note that some lines, once closed, cannot be reopened. Attempts
* to reopen such a line will always result in an <code>LineUnavailableException</code>.
* <p>
* Some types of lines have configurable properties that may affect
* resource allocation. For example, a <code>DataLine</code> must
* be opened with a particular format and buffer size. Such lines
* should provide a mechanism for configuring these properties, such
* as an additional <code>open</code> method or methods which allow
* an application to specify the desired settings.
* <p>
* This method takes no arguments, and opens the line with the current
* settings. For <code>{@link SourceDataLine}</code> and
* <code>{@link TargetDataLine}</code> objects, this means that the line is
* opened with default settings. For a <code>{@link Clip}</code>, however,
* the buffer size is determined when data is loaded. Since this method does not
* allow the application to specify any data to load, an IllegalArgumentException
* is thrown. Therefore, you should instead use one of the <code>open</code> methods
* provided in the <code>Clip</code> interface to load data into the <code>Clip</code>.
* <p>
* For <code>DataLine</code>'s, if the <code>DataLine.Info</code>
* object which was used to retrieve the line, specifies at least
* one fully qualified audio format, the last one will be used
* as the default format.
*
* @throws IllegalArgumentException if this method is called on a Clip instance.
* @throws LineUnavailableException if the line cannot be
* opened due to resource restrictions.
* @throws SecurityException if the line cannot be
* opened due to security restrictions.
*
* @see #close
* @see #isOpen
* @see LineEvent
* @see DataLine
* @see Clip#open(AudioFormat, byte[], int, int)
* @see Clip#open(AudioInputStream)
*/
public void open() throws LineUnavailableException;
/**
* Closes the line, indicating that any system resources
* in use by the line can be released. If this operation
* succeeds, the line is marked closed and a <code>CLOSE</code> event is dispatched
* to the line's listeners.
* @throws SecurityException if the line cannot be
* closed due to security restrictions.
*
* @see #open
* @see #isOpen
* @see LineEvent
*/
public void close();
/**
* Indicates whether the line is open, meaning that it has reserved
* system resources and is operational, although it might not currently be
* playing or capturing sound.
* @return <code>true</code> if the line is open, otherwise <code>false</code>
*
* @see #open()
* @see #close()
*/
public boolean isOpen();
/**
* Obtains the set of controls associated with this line.
* Some controls may only be available when the line is open.
* If there are no controls, this method returns an array of length 0.
* @return the array of controls
* @see #getControl
*/
public Control[] getControls();
/**
* Indicates whether the line supports a control of the specified type.
* Some controls may only be available when the line is open.
* @param control the type of the control for which support is queried
* @return <code>true</code> if at least one control of the specified type is
* supported, otherwise <code>false</code>.
*/
public boolean isControlSupported(Control.Type control);
/**
* Obtains a control of the specified type,
* if there is any.
* Some controls may only be available when the line is open.
* @param control the type of the requested control
* @return a control of the specified type
* @throws IllegalArgumentException if a control of the specified type
* is not supported
* @see #getControls
* @see #isControlSupported(Control.Type control)
*/
public Control getControl(Control.Type control);
/**
* Adds a listener to this line. Whenever the line's status changes, the
* listener's <code>update()</code> method is called with a <code>LineEvent</code> object
* that describes the change.
* @param listener the object to add as a listener to this line
* @see #removeLineListener
* @see LineListener#update
* @see LineEvent
*/
public void addLineListener(LineListener listener);
/**
* Removes the specified listener from this line's list of listeners.
* @param listener listener to remove
* @see #addLineListener
*/
public void removeLineListener(LineListener listener);
/**
* A <code>Line.Info</code> object contains information about a line.
* The only information provided by <code>Line.Info</code> itself
* is the Java class of the line.
* A subclass of <code>Line.Info</code> adds other kinds of information
* about the line. This additional information depends on which <code>Line</code>
* subinterface is implemented by the kind of line that the <code>Line.Info</code>
* subclass describes.
* <p>
* A <code>Line.Info</code> can be retrieved using various methods of
* the <code>Line</code>, <code>Mixer</code>, and <code>AudioSystem</code>
* interfaces. Other such methods let you pass a <code>Line.Info</code> as
* an argument, to learn whether lines matching the specified configuration
* are available and to obtain them.
*
* @author Kara Kytle
*
* @see Line#getLineInfo
* @see Mixer#getSourceLineInfo
* @see Mixer#getTargetLineInfo
* @see Mixer#getLine <code>Mixer.getLine(Line.Info)</code>
* @see Mixer#getSourceLineInfo(Line.Info) <code>Mixer.getSourceLineInfo(Line.Info)</code>
* @see Mixer#getSourceLineInfo(Line.Info) <code>Mixer.getTargetLineInfo(Line.Info)</code>
* @see Mixer#isLineSupported <code>Mixer.isLineSupported(Line.Info)</code>
* @see AudioSystem#getLine <code>AudioSystem.getLine(Line.Info)</code>
* @see AudioSystem#getSourceLineInfo <code>AudioSystem.getSourceLineInfo(Line.Info)</code>
* @see AudioSystem#getTargetLineInfo <code>AudioSystem.getTargetLineInfo(Line.Info)</code>
* @see AudioSystem#isLineSupported <code>AudioSystem.isLineSupported(Line.Info)</code>
* @since 1.3
*/
public static class Info {
/**
* The class of the line described by the info object.
*/
private final Class lineClass;
/**
* Constructs an info object that describes a line of the specified class.
* This constructor is typically used by an application to
* describe a desired line.
* @param lineClass the class of the line that the new Line.Info object describes
*/
public Info(Class<?> lineClass) {
if (lineClass == null) {
this.lineClass = Line.class;
} else {
this.lineClass = lineClass;
}
}
/**
* Obtains the class of the line that this Line.Info object describes.
* @return the described line's class
*/
public Class<?> getLineClass() {
return lineClass;
}
/**
* Indicates whether the specified info object matches this one.
* To match, the specified object must be identical to or
* a special case of this one. The specified info object
* must be either an instance of the same class as this one,
* or an instance of a sub-type of this one. In addition, the
* attributes of the specified object must be compatible with the
* capabilities of this one. Specifically, the routing configuration
* for the specified info object must be compatible with that of this
* one.
* Subclasses may add other criteria to determine whether the two objects
* match.
*
* @param info the info object which is being compared to this one
* @return <code>true</code> if the specified object matches this one,
* <code>false</code> otherwise
*/
public boolean matches(Info info) {
// $$kk: 08.30.99: is this backwards?
// dataLine.matches(targetDataLine) == true: targetDataLine is always dataLine
// targetDataLine.matches(dataLine) == false
// so if i want to make sure i get a targetDataLine, i need:
// targetDataLine.matches(prospective_match) == true
// => prospective_match may be other things as well, but it is at least a targetDataLine
// targetDataLine defines the requirements which prospective_match must meet.
// "if this Class object represents a declared class, this method returns
// true if the specified Object argument is an instance of the represented
// class (or of any of its subclasses)"
// GainControlClass.isInstance(MyGainObj) => true
// GainControlClass.isInstance(MySpecialGainInterfaceObj) => true
// this_class.isInstance(that_object) => that object can by cast to this class
// => that_object's class may be a subtype of this_class
// => that may be more specific (subtype) of this
// "If this Class object represents an interface, this method returns true
// if the class or any superclass of the specified Object argument implements
// this interface"
// GainControlClass.isInstance(MyGainObj) => true
// GainControlClass.isInstance(GenericControlObj) => may be false
// => that may be more specific
if (! (this.getClass().isInstance(info)) ) {
return false;
}
// this.isAssignableFrom(that) => this is same or super to that
// => this is at least as general as that
// => that may be subtype of this
if (! (getLineClass().isAssignableFrom(info.getLineClass())) ) {
return false;
}
return true;
}
/**
* Obtains a textual description of the line info.
* @return a string description
*/
public String toString() {
String fullPackagePath = "javax.sound.sampled.";
String initialString = new String(getLineClass().toString());
String finalString;
int index = initialString.indexOf(fullPackagePath);
if (index != -1) {
finalString = initialString.substring(0, index) + initialString.substring( (index + fullPackagePath.length()), initialString.length() );
} else {
finalString = initialString;
}
return finalString;
}
} // class Info
} // interface Line

View File

@@ -0,0 +1,281 @@
/*
* Copyright (c) 1999, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* The <code>LineEvent</code> class encapsulates information that a line
* sends its listeners whenever the line opens, closes, starts, or stops.
* Each of these four state changes is represented by a corresponding
* type of event. A listener receives the event as a parameter to its
* {@link LineListener#update update} method. By querying the event,
* the listener can learn the type of event, the line responsible for
* the event, and how much data the line had processed when the event occurred.
*
* <p>Although this class implements Serializable, attempts to
* serialize a <code>LineEvent</code> object will fail.
*
* @author Kara Kytle
*
* @see Line
* @see LineListener#update
* @since 1.3
*
* @serial exclude
*/
public class LineEvent extends java.util.EventObject {
// INSTANCE VARIABLES
/**
* The kind of line event (<code>OPEN</code>, <code>CLOSE</code>,
* <code>START</code>, or <code>STOP</code>).
* @see #getType
* @serial
*/
private final Type type;
/**
* The media position when the event occurred, expressed in sample frames.
* Note that this field is only relevant to certain events generated by
* data lines, such as <code>START</code> and <code>STOP</code>. For
* events generated by lines that do not count sample frames, and for any
* other events for which this value is not known, the position value
* should be {@link AudioSystem#NOT_SPECIFIED}.
* @serial
* @see #getFramePosition
*/
private final long position;
/**
* Constructs a new event of the specified type, originating from the specified line.
* @param line the source of this event
* @param type the event type (<code>OPEN</code>, <code>CLOSE</code>, <code>START</code>, or <code>STOP</code>)
* @param position the number of sample frames that the line had already processed when the event occurred,
* or {@link AudioSystem#NOT_SPECIFIED}
*
* @throws IllegalArgumentException if <code>line</code> is
* <code>null</code>.
*/
public LineEvent(Line line, Type type, long position) {
super(line);
this.type = type;
this.position = position;
}
/**
* Obtains the audio line that is the source of this event.
* @return the line responsible for this event
*/
public final Line getLine() {
return (Line)getSource();
}
/**
* Obtains the event's type.
* @return this event's type ({@link Type#OPEN}, {@link Type#CLOSE},
* {@link Type#START}, or {@link Type#STOP})
*/
public final Type getType() {
return type;
}
/**
* Obtains the position in the line's audio data when the event occurred, expressed in sample frames.
* For example, if a source line had already played back 14 sample frames at the time it was
* paused, the pause event would report the line's position as 14. The next frame to be processed
* would be frame number 14 using zero-based numbering, or 15 using one-based numbering.
* <p>
* Note that this field is relevant only to certain events generated by
* data lines, such as <code>START</code> and <code>STOP</code>. For
* events generated by lines that do not count sample frames, and for any
* other events for which this value is not known, the position value
* should be {@link AudioSystem#NOT_SPECIFIED}.
*
* @return the line's position as a sample frame number
*/
/*
* $$kk: 04.20.99: note to myself: should make sure our implementation is consistent with this.
* which is a reasonable definition....
*/
public final long getFramePosition() {
return position;
}
/**
* Obtains a string representation of the event. The contents of the string may vary
* between implementations of Java Sound.
* @return a string describing the event.
*/
public String toString() {
String sType = "";
if (type != null) sType = type.toString()+" ";
String sLine;
if (getLine() == null) {
sLine = "null";
} else {
sLine = getLine().toString();
}
return new String(sType + "event from line " + sLine);
}
/**
* The LineEvent.Type inner class identifies what kind of event occurred on a line.
* Static instances are provided for the common types (OPEN, CLOSE, START, and STOP).
*
* @see LineEvent#getType()
*/
public static class Type {
/**
* Type name.
*/
// $$kk: 03.25.99: why can't this be final??
private /*final*/ String name;
/**
* Constructs a new event type.
* @param name name of the type
*/
protected Type(String name) {
this.name = name;
}
//$$fb 2002-11-26: fix for 4695001: SPEC: description of equals() method contains typo
/**
* Indicates whether the specified object is equal to this event type,
* returning <code>true</code> if the objects are identical.
* @param obj the reference object with which to compare
* @return <code>true</code> if this event type is the same as
* <code>obj</code>; <code>false</code> otherwise
*/
public final boolean equals(Object obj) {
return super.equals(obj);
}
/**
* Finalizes the hashcode method.
*/
public final int hashCode() {
return super.hashCode();
}
/**
* Returns the type name as the string representation.
*/
public String toString() {
return name;
}
// LINE EVENT TYPE DEFINES
/**
* A type of event that is sent when a line opens, reserving system
* resources for itself.
* @see #CLOSE
* @see Line#open
*/
public static final Type OPEN = new Type("Open");
/**
* A type of event that is sent when a line closes, freeing the system
* resources it had obtained when it was opened.
* @see #OPEN
* @see Line#close
*/
public static final Type CLOSE = new Type("Close");
/**
* A type of event that is sent when a line begins to engage in active
* input or output of audio data in response to a
* {@link DataLine#start start} request.
* @see #STOP
* @see DataLine#start
*/
public static final Type START = new Type("Start");
/**
* A type of event that is sent when a line ceases active input or output
* of audio data in response to a {@link DataLine#stop stop} request,
* or because the end of media has been reached.
* @see #START
* @see DataLine#stop
*/
public static final Type STOP = new Type("Stop");
/**
* A type of event that is sent when a line ceases to engage in active
* input or output of audio data because the end of media has been reached.
*/
/*
* ISSUE: we may want to get rid of this. Is JavaSound
* responsible for reporting this??
*
* [If it's decided to keep this API, the docs will need to be updated to include mention
* of EOM events elsewhere.]
*/
//public static final Type EOM = new Type("EOM");
/**
* A type of event that is sent when a line begins to engage in active
* input or output of audio data. Examples of when this happens are
* when a source line begins or resumes writing data to its mixer, and
* when a target line begins or resumes reading data from its mixer.
* @see #STOP
* @see SourceDataLine#write
* @see TargetDataLine#read
* @see DataLine#start
*/
//public static final Type ACTIVE = new Type("ACTIVE");
/**
* A type of event that is sent when a line ceases active input or output
* of audio data.
* @see #START
* @see DataLine#stop
*/
//public static final Type INACTIVE = new Type("INACTIVE");
} // class Type
} // class LineEvent

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* Instances of classes that implement the <code>LineListener</code> interface can register to
* receive events when a line's status changes.
*
* @author Kara Kytle
*
* @see Line
* @see Line#addLineListener
* @see Line#removeLineListener
* @see LineEvent
*
* @since 1.3
*/
/*
* Instances of classes that implement the <code>LineListener</code> interface can register to
* receive events when a line's status changes.
*
* @see Line
* @see Line#addLineListener
* @see Line#removeLineListener
* @see LineEvent
*
* @author Kara Kytle
*/
public interface LineListener extends java.util.EventListener {
/**
* Informs the listener that a line's state has changed. The listener can then invoke
* <code>LineEvent</code> methods to obtain information about the event.
* @param event a line event that describes the change
*/
/*
* Informs the listener that a line's state has changed. The listener can then invoke
* <code>LineEvent</code> methods to obtain information about the event.
* @param event a line event that describes the change
*/
public void update(LineEvent event);
} // interface LineListener

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* A <code>LineUnavailableException</code> is an exception indicating that a
* line cannot be opened because it is unavailable. This situation
* arises most commonly when a requested line is already in use
* by another application.
*
* @author Kara Kytle
* @since 1.3
*/
/*
* A <code>LinenavailableException</code> is an exception indicating that a
* line annot be opened because it is unavailable. This situation
* arises most commonly when a line is requested when it is already in use
* by another application.
*
* @author Kara Kytle
*/
public class LineUnavailableException extends Exception {
/**
* Constructs a <code>LineUnavailableException</code> that has
* <code>null</code> as its error detail message.
*/
public LineUnavailableException() {
super();
}
/**
* Constructs a <code>LineUnavailableException</code> that has
* the specified detail message.
*
* @param message a string containing the error detail message
*/
public LineUnavailableException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,354 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* A mixer is an audio device with one or more lines. It need not be
* designed for mixing audio signals. A mixer that actually mixes audio
* has multiple input (source) lines and at least one output (target) line.
* The former are often instances of classes that implement
* <code>{@link SourceDataLine}</code>,
* and the latter, <code>{@link TargetDataLine}</code>. <code>{@link Port}</code>
* objects, too, are either source lines or target lines.
* A mixer can accept prerecorded, loopable sound as input, by having
* some of its source lines be instances of objects that implement the
* <code>{@link Clip}</code> interface.
* <p>
* Through methods of the <code>Line</code> interface, which <code>Mixer</code> extends,
* a mixer might provide a set of controls that are global to the mixer. For example,
* the mixer can have a master gain control. These global controls are distinct
* from the controls belonging to each of the mixer's individual lines.
* <p>
* Some mixers, especially
* those with internal digital mixing capabilities, may provide
* additional capabilities by implementing the <code>DataLine</code> interface.
* <p>
* A mixer can support synchronization of its lines. When one line in
* a synchronized group is started or stopped, the other lines in the group
* automatically start or stop simultaneously with the explicitly affected one.
*
* @author Kara Kytle
* @since 1.3
*/
public interface Mixer extends Line {
/**
* Obtains information about this mixer, including the product's name,
* version, vendor, etc.
* @return a mixer info object that describes this mixer
* @see Mixer.Info
*/
public Info getMixerInfo();
/**
* Obtains information about the set of source lines supported
* by this mixer.
* Some source lines may only be available when this mixer is open.
* @return array of <code>Line.Info</code> objects representing source lines
* for this mixer. If no source lines are supported,
* an array of length 0 is returned.
*/
public Line.Info[] getSourceLineInfo();
/**
* Obtains information about the set of target lines supported
* by this mixer.
* Some target lines may only be available when this mixer is open.
* @return array of <code>Line.Info</code> objects representing target lines
* for this mixer. If no target lines are supported,
* an array of length 0 is returned.
*/
public Line.Info[] getTargetLineInfo();
/**
* Obtains information about source lines of a particular type supported
* by the mixer.
* Some source lines may only be available when this mixer is open.
* @param info a <code>Line.Info</code> object describing lines about which information
* is queried
* @return an array of <code>Line.Info</code> objects describing source lines matching
* the type requested. If no matching source lines are supported, an array of length 0
* is returned.
*/
public Line.Info[] getSourceLineInfo(Line.Info info);
/**
* Obtains information about target lines of a particular type supported
* by the mixer.
* Some target lines may only be available when this mixer is open.
* @param info a <code>Line.Info</code> object describing lines about which information
* is queried
* @return an array of <code>Line.Info</code> objects describing target lines matching
* the type requested. If no matching target lines are supported, an array of length 0
* is returned.
*/
public Line.Info[] getTargetLineInfo(Line.Info info);
/**
* Indicates whether the mixer supports a line (or lines) that match
* the specified <code>Line.Info</code> object.
* Some lines may only be supported when this mixer is open.
* @param info describes the line for which support is queried
* @return <code>true</code> if at least one matching line is
* supported, <code>false</code> otherwise
*/
public boolean isLineSupported(Line.Info info);
/**
* Obtains a line that is available for use and that matches the description
* in the specified <code>Line.Info</code> object.
*
* <p>If a <code>DataLine</code> is requested, and <code>info</code>
* is an instance of <code>DataLine.Info</code> specifying at
* least one fully qualified audio format, the last one
* will be used as the default format of the returned
* <code>DataLine</code>.
*
* @param info describes the desired line
* @return a line that is available for use and that matches the description
* in the specified {@code Line.Info} object
* @throws LineUnavailableException if a matching line
* is not available due to resource restrictions
* @throws IllegalArgumentException if this mixer does
* not support any lines matching the description
* @throws SecurityException if a matching line
* is not available due to security restrictions
*/
public Line getLine(Line.Info info) throws LineUnavailableException;
//$$fb 2002-04-12: fix for 4667258: behavior of Mixer.getMaxLines(Line.Info) method doesn't match the spec
/**
* Obtains the approximate maximum number of lines of the requested type that can be open
* simultaneously on the mixer.
*
* Certain types of mixers do not have a hard bound and may allow opening more lines.
* Since certain lines are a shared resource, a mixer may not be able to open the maximum
* number of lines if another process has opened lines of this mixer.
*
* The requested type is any line that matches the description in
* the provided <code>Line.Info</code> object. For example, if the info
* object represents a speaker
* port, and the mixer supports exactly one speaker port, this method
* should return 1. If the info object represents a source data line
* and the mixer supports the use of 32 source data lines simultaneously,
* the return value should be 32.
* If there is no limit, this function returns <code>AudioSystem.NOT_SPECIFIED</code>.
* @param info a <code>Line.Info</code> that describes the line for which
* the number of supported instances is queried
* @return the maximum number of matching lines supported, or <code>AudioSystem.NOT_SPECIFIED</code>
*/
public int getMaxLines(Line.Info info);
/**
* Obtains the set of all source lines currently open to this mixer.
*
* @return the source lines currently open to the mixer.
* If no source lines are currently open to this mixer, an
* array of length 0 is returned.
* @throws SecurityException if the matching lines
* are not available due to security restrictions
*/
public Line[] getSourceLines();
/**
* Obtains the set of all target lines currently open from this mixer.
*
* @return target lines currently open from the mixer.
* If no target lines are currently open from this mixer, an
* array of length 0 is returned.
* @throws SecurityException if the matching lines
* are not available due to security restrictions
*/
public Line[] getTargetLines();
/**
* Synchronizes two or more lines. Any subsequent command that starts or stops
* audio playback or capture for one of these lines will exert the
* same effect on the other lines in the group, so that they start or stop playing or
* capturing data simultaneously.
*
* @param lines the lines that should be synchronized
* @param maintainSync <code>true</code> if the synchronization
* must be precisely maintained (i.e., the synchronization must be sample-accurate)
* at all times during operation of the lines , or <code>false</code>
* if precise synchronization is required only during start and stop operations
*
* @throws IllegalArgumentException if the lines cannot be synchronized.
* This may occur if the lines are of different types or have different
* formats for which this mixer does not support synchronization, or if
* all lines specified do not belong to this mixer.
*/
public void synchronize(Line[] lines, boolean maintainSync);
/**
* Releases synchronization for the specified lines. The array must
* be identical to one for which synchronization has already been
* established; otherwise an exception may be thrown. However, <code>null</code>
* may be specified, in which case all currently synchronized lines that belong
* to this mixer are unsynchronized.
* @param lines the synchronized lines for which synchronization should be
* released, or <code>null</code> for all this mixer's synchronized lines
*
* @throws IllegalArgumentException if the lines cannot be unsynchronized.
* This may occur if the argument specified does not exactly match a set
* of lines for which synchronization has already been established.
*/
public void unsynchronize(Line[] lines);
/**
* Reports whether this mixer supports synchronization of the specified set of lines.
*
* @param lines the set of lines for which synchronization support is queried
* @param maintainSync <code>true</code> if the synchronization
* must be precisely maintained (i.e., the synchronization must be sample-accurate)
* at all times during operation of the lines , or <code>false</code>
* if precise synchronization is required only during start and stop operations
*
* @return <code>true</code> if the lines can be synchronized, <code>false</code>
* otherwise
*/
public boolean isSynchronizationSupported(Line[] lines, boolean maintainSync);
/**
* The <code>Mixer.Info</code> class represents information about an audio mixer,
* including the product's name, version, and vendor, along with a textual
* description. This information may be retrieved through the
* {@link Mixer#getMixerInfo() getMixerInfo}
* method of the <code>Mixer</code> interface.
*
* @author Kara Kytle
* @since 1.3
*/
public static class Info {
/**
* Mixer name.
*/
private final String name;
/**
* Mixer vendor.
*/
private final String vendor;
/**
* Mixer description.
*/
private final String description;
/**
* Mixer version.
*/
private final String version;
/**
* Constructs a mixer's info object, passing it the given
* textual information.
* @param name the name of the mixer
* @param vendor the company who manufactures or creates the hardware
* or software mixer
* @param description descriptive text about the mixer
* @param version version information for the mixer
*/
protected Info(String name, String vendor, String description, String version) {
this.name = name;
this.vendor = vendor;
this.description = description;
this.version = version;
}
/**
* Indicates whether two info objects are equal, returning <code>true</code> if
* they are identical.
* @param obj the reference object with which to compare this info
* object
* @return <code>true</code> if this info object is the same as the
* <code>obj</code> argument; <code>false</code> otherwise
*/
public final boolean equals(Object obj) {
return super.equals(obj);
}
/**
* Finalizes the hashcode method.
*
* @return the hashcode for this object
*/
public final int hashCode() {
return super.hashCode();
}
/**
* Obtains the name of the mixer.
* @return a string that names the mixer
*/
public final String getName() {
return name;
}
/**
* Obtains the vendor of the mixer.
* @return a string that names the mixer's vendor
*/
public final String getVendor() {
return vendor;
}
/**
* Obtains the description of the mixer.
* @return a textual description of the mixer
*/
public final String getDescription() {
return description;
}
/**
* Obtains the version of the mixer.
* @return textual version information for the mixer
*/
public final String getVersion() {
return version;
}
/**
* Provides a string representation of the mixer info.
* @return a string describing the info object
*/
public final String toString() {
return (name + ", version " + version);
}
} // class Info
}

View File

@@ -0,0 +1,208 @@
/*
* Copyright (c) 1999, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* Ports are simple lines for input or output of audio to or from audio devices.
* Common examples of ports that act as source lines (mixer inputs) include the microphone,
* line input, and CD-ROM drive. Ports that act as target lines (mixer outputs) include the
* speaker, headphone, and line output. You can access port using a <code>{@link Port.Info}</code>
* object.
*
* @author Kara Kytle
* @since 1.3
*/
public interface Port extends Line {
// INNER CLASSES
/**
* The <code>Port.Info</code> class extends <code>{@link Line.Info}</code>
* with additional information specific to ports, including the port's name
* and whether it is a source or a target for its mixer.
* By definition, a port acts as either a source or a target to its mixer,
* but not both. (Audio input ports are sources; audio output ports are targets.)
* <p>
* To learn what ports are available, you can retrieve port info objects through the
* <code>{@link Mixer#getSourceLineInfo getSourceLineInfo}</code> and
* <code>{@link Mixer#getTargetLineInfo getTargetLineInfo}</code>
* methods of the <code>Mixer</code> interface. Instances of the
* <code>Port.Info</code> class may also be constructed and used to obtain
* lines matching the parameters specified in the <code>Port.Info</code> object.
*
* @author Kara Kytle
* @since 1.3
*/
public static class Info extends Line.Info {
// AUDIO PORT TYPE DEFINES
// SOURCE PORTS
/**
* A type of port that gets audio from a built-in microphone or a microphone jack.
*/
public static final Info MICROPHONE = new Info(Port.class,"MICROPHONE", true);
/**
* A type of port that gets audio from a line-level audio input jack.
*/
public static final Info LINE_IN = new Info(Port.class,"LINE_IN", true);
/**
* A type of port that gets audio from a CD-ROM drive.
*/
public static final Info COMPACT_DISC = new Info(Port.class,"COMPACT_DISC", true);
// TARGET PORTS
/**
* A type of port that sends audio to a built-in speaker or a speaker jack.
*/
public static final Info SPEAKER = new Info(Port.class,"SPEAKER", false);
/**
* A type of port that sends audio to a headphone jack.
*/
public static final Info HEADPHONE = new Info(Port.class,"HEADPHONE", false);
/**
* A type of port that sends audio to a line-level audio output jack.
*/
public static final Info LINE_OUT = new Info(Port.class,"LINE_OUT", false);
// FUTURE DIRECTIONS...
// telephone
// DAT
// DVD
// INSTANCE VARIABLES
private String name;
private boolean isSource;
// CONSTRUCTOR
/**
* Constructs a port's info object from the information given.
* This constructor is typically used by an implementation
* of Java Sound to describe a supported line.
*
* @param lineClass the class of the port described by the info object.
* @param name the string that names the port
* @param isSource <code>true</code> if the port is a source port (such
* as a microphone), <code>false</code> if the port is a target port
* (such as a speaker).
*/
public Info(Class<?> lineClass, String name, boolean isSource) {
super(lineClass);
this.name = name;
this.isSource = isSource;
}
// METHODS
/**
* Obtains the name of the port.
* @return the string that names the port
*/
public String getName() {
return name;
}
/**
* Indicates whether the port is a source or a target for its mixer.
* @return <code>true</code> if the port is a source port (such
* as a microphone), <code>false</code> if the port is a target port
* (such as a speaker).
*/
public boolean isSource() {
return isSource;
}
/**
* Indicates whether this info object specified matches this one.
* To match, the match requirements of the superclass must be
* met and the types must be equal.
* @param info the info object for which the match is queried
*/
public boolean matches(Line.Info info) {
if (! (super.matches(info)) ) {
return false;
}
if (!(name.equals(((Info)info).getName())) ) {
return false;
}
if (! (isSource == ((Info)info).isSource()) ) {
return false;
}
return true;
}
/**
* Finalizes the equals method
*/
public final boolean equals(Object obj) {
return super.equals(obj);
}
/**
* Finalizes the hashCode method
*/
public final int hashCode() {
return super.hashCode();
}
/**
* Provides a <code>String</code> representation
* of the port.
* @return a string that describes the port
*/
public final String toString() {
return (name + ((isSource == true) ? " source" : " target") + " port");
}
} // class Info
}

View File

@@ -0,0 +1,299 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* The <code>ReverbType</code> class provides methods for
* accessing various reverberation settings to be applied to
* an audio signal.
* <p>
* Reverberation simulates the reflection of sound off of
* the walls, ceiling, and floor of a room. Depending on
* the size of the room, and how absorbent or reflective the materials in the
* room's surfaces are, the sound might bounce around for a
* long time before dying away.
* <p>
* The reverberation parameters provided by <code>ReverbType</code> consist
* of the delay time and intensity of early reflections, the delay time and
* intensity of late reflections, and an overall decay time.
* Early reflections are the initial individual low-order reflections of the
* direct signal off the surfaces in the room.
* The late Reflections are the dense, high-order reflections that characterize
* the room's reverberation.
* The delay times for the start of these two reflection types give the listener
* a sense of the overall size and complexity of the room's shape and contents.
* The larger the room, the longer the reflection delay times.
* The early and late reflections' intensities define the gain (in decibels) of the reflected
* signals as compared to the direct signal. These intensities give the
* listener an impression of the absorptive nature of the surfaces and objects
* in the room.
* The decay time defines how long the reverberation takes to exponentially
* decay until it is no longer perceptible ("effective zero").
* The larger and less absorbent the surfaces, the longer the decay time.
* <p>
* The set of parameters defined here may not include all aspects of reverberation
* as specified by some systems. For example, the Midi Manufacturer's Association
* (MMA) has an Interactive Audio Special Interest Group (IASIG), which has a
* 3-D Working Group that has defined a Level 2 Spec (I3DL2). I3DL2
* supports filtering of reverberation and
* control of reverb density. These properties are not included in the JavaSound 1.0
* definition of a reverb control. In such a case, the implementing system
* should either extend the defined reverb control to include additional
* parameters, or else interpret the system's additional capabilities in a way that fits
* the model described here.
* <p>
* If implementing JavaSound on a I3DL2-compliant device:
* <ul>
* <li>Filtering is disabled (high-frequency attenuations are set to 0.0 dB)
* <li>Density parameters are set to midway between minimum and maximum
* </ul>
* <p>
* The following table shows what parameter values an implementation might use for a
* representative set of reverberation settings.
* <p>
*
* <b>Reverberation Types and Parameters</b>
* <p>
* <table border=1 cellpadding=5 summary="reverb types and params: decay time, late intensity, late delay, early intensity, and early delay">
*
* <tr>
* <th>Type</th>
* <th>Decay Time (ms)</th>
* <th>Late Intensity (dB)</th>
* <th>Late Delay (ms)</th>
* <th>Early Intensity (dB)</th>
* <th>Early Delay(ms)</th>
* </tr>
*
* <tr>
* <td>Cavern</td>
* <td>2250</td>
* <td>-2.0</td>
* <td>41.3</td>
* <td>-1.4</td>
* <td>10.3</td>
* </tr>
*
* <tr>
* <td>Dungeon</td>
* <td>1600</td>
* <td>-1.0</td>
* <td>10.3</td>
* <td>-0.7</td>
* <td>2.6</td>
* </tr>
*
* <tr>
* <td>Garage</td>
* <td>900</td>
* <td>-6.0</td>
* <td>14.7</td>
* <td>-4.0</td>
* <td>3.9</td>
* </tr>
*
* <tr>
* <td>Acoustic Lab</td>
* <td>280</td>
* <td>-3.0</td>
* <td>8.0</td>
* <td>-2.0</td>
* <td>2.0</td>
* </tr>
*
* <tr>
* <td>Closet</td>
* <td>150</td>
* <td>-10.0</td>
* <td>2.5</td>
* <td>-7.0</td>
* <td>0.6</td>
* </tr>
*
* </table>
*
* @author Kara Kytle
* @since 1.3
*/
public class ReverbType {
/**
* Descriptive name of the reverb type..
*/
private String name;
/**
* Early reflection delay in microseconds.
*/
private int earlyReflectionDelay;
/**
* Early reflection intensity.
*/
private float earlyReflectionIntensity;
/**
* Late reflection delay in microseconds.
*/
private int lateReflectionDelay;
/**
* Late reflection intensity.
*/
private float lateReflectionIntensity;
/**
* Total decay time
*/
private int decayTime;
/**
* Constructs a new reverb type that has the specified reverberation
* parameter values.
* @param name the name of the new reverb type, or a zero-length <code>String</code>
* @param earlyReflectionDelay the new type's early reflection delay time in microseconds
* @param earlyReflectionIntensity the new type's early reflection intensity in dB
* @param lateReflectionDelay the new type's late reflection delay time in microseconds
* @param lateReflectionIntensity the new type's late reflection intensity in dB
* @param decayTime the new type's decay time in microseconds
*/
protected ReverbType(String name, int earlyReflectionDelay, float earlyReflectionIntensity, int lateReflectionDelay, float lateReflectionIntensity, int decayTime) {
this.name = name;
this.earlyReflectionDelay = earlyReflectionDelay;
this.earlyReflectionIntensity = earlyReflectionIntensity;
this.lateReflectionDelay = lateReflectionDelay;
this.lateReflectionIntensity = lateReflectionIntensity;
this.decayTime = decayTime;
}
/**
* Obtains the name of this reverb type.
* @return the name of this reverb type
* @since 1.5
*/
public String getName() {
return name;
}
/**
* Returns the early reflection delay time in microseconds.
* This is the amount of time between when the direct signal is
* heard and when the first early reflections are heard.
* @return early reflection delay time for this reverb type, in microseconds
*/
public final int getEarlyReflectionDelay() {
return earlyReflectionDelay;
}
/**
* Returns the early reflection intensity in decibels.
* This is the amplitude attenuation of the first early reflections
* relative to the direct signal.
* @return early reflection intensity for this reverb type, in dB
*/
public final float getEarlyReflectionIntensity() {
return earlyReflectionIntensity;
}
/**
* Returns the late reflection delay time in microseconds.
* This is the amount of time between when the first early reflections
* are heard and when the first late reflections are heard.
* @return late reflection delay time for this reverb type, in microseconds
*/
public final int getLateReflectionDelay() {
return lateReflectionDelay;
}
/**
* Returns the late reflection intensity in decibels.
* This is the amplitude attenuation of the first late reflections
* relative to the direct signal.
* @return late reflection intensity for this reverb type, in dB
*/
public final float getLateReflectionIntensity() {
return lateReflectionIntensity;
}
/**
* Obtains the decay time, which is the amount of time over which the
* late reflections attenuate to effective zero. The effective zero
* value is implementation-dependent.
* @return the decay time of the late reflections, in microseconds
*/
public final int getDecayTime() {
return decayTime;
}
/**
* Indicates whether the specified object is equal to this reverb type,
* returning <code>true</code> if the objects are identical.
* @param obj the reference object with which to compare
* @return <code>true</code> if this reverb type is the same as
* <code>obj</code>; <code>false</code> otherwise
*/
public final boolean equals(Object obj) {
return super.equals(obj);
}
/**
* Finalizes the hashcode method.
*/
public final int hashCode() {
return super.hashCode();
}
/**
* Provides a <code>String</code> representation of the reverb type,
* including its name and its parameter settings.
* The exact contents of the string may vary between implementations of
* Java Sound.
* @return reverberation type name and description
*/
public final String toString() {
//$$fb2001-07-20: fix for bug 4385060: The "name" attribute of class "ReverbType" is not accessible.
//return (super.toString() + ", early reflection delay " + earlyReflectionDelay +
return (name + ", early reflection delay " + earlyReflectionDelay +
" ns, early reflection intensity " + earlyReflectionIntensity +
" dB, late deflection delay " + lateReflectionDelay +
" ns, late reflection intensity " + lateReflectionIntensity +
" dB, decay time " + decayTime);
}
} // class ReverbType

View File

@@ -0,0 +1,203 @@
/*
* Copyright (c) 1999, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* A source data line is a data line to which data may be written. It acts as
* a source to its mixer. An application writes audio bytes to a source data line,
* which handles the buffering of the bytes and delivers them to the mixer.
* The mixer may mix the samples with those from other sources and then deliver
* the mix to a target such as an output port (which may represent an audio output
* device on a sound card).
* <p>
* Note that the naming convention for this interface reflects the relationship
* between the line and its mixer. From the perspective of an application,
* a source data line may act as a target for audio data.
* <p>
* A source data line can be obtained from a mixer by invoking the
* <code>{@link Mixer#getLine getLine}</code> method of <code>Mixer</code> with
* an appropriate <code>{@link DataLine.Info}</code> object.
* <p>
* The <code>SourceDataLine</code> interface provides a method for writing
* audio data to the data line's buffer. Applications that play or mix
* audio should write data to the source data line quickly enough to keep the
* buffer from underflowing (emptying), which could cause discontinuities in
* the audio that are perceived as clicks. Applications can use the
* <code>{@link DataLine#available available}</code> method defined in the
* <code>DataLine</code> interface to determine the amount of data currently
* queued in the data line's buffer. The amount of data which can be written
* to the buffer without blocking is the difference between the buffer size
* and the amount of queued data. If the delivery of audio output
* stops due to underflow, a <code>{@link LineEvent.Type#STOP STOP}</code> event is
* generated. A <code>{@link LineEvent.Type#START START}</code> event is generated
* when the audio output resumes.
*
* @author Kara Kytle
* @see Mixer
* @see DataLine
* @see TargetDataLine
* @since 1.3
*/
public interface SourceDataLine extends DataLine {
/**
* Opens the line with the specified format and suggested buffer size,
* causing the line to acquire any required
* system resources and become operational.
* <p>
* The buffer size is specified in bytes, but must represent an integral
* number of sample frames. Invoking this method with a requested buffer
* size that does not meet this requirement may result in an
* IllegalArgumentException. The actual buffer size for the open line may
* differ from the requested buffer size. The value actually set may be
* queried by subsequently calling <code>{@link DataLine#getBufferSize}</code>.
* <p>
* If this operation succeeds, the line is marked as open, and an
* <code>{@link LineEvent.Type#OPEN OPEN}</code> event is dispatched to the
* line's listeners.
* <p>
* Invoking this method on a line which is already open is illegal
* and may result in an <code>IllegalStateException</code>.
* <p>
* Note that some lines, once closed, cannot be reopened. Attempts
* to reopen such a line will always result in a
* <code>LineUnavailableException</code>.
*
* @param format the desired audio format
* @param bufferSize the desired buffer size
* @throws LineUnavailableException if the line cannot be
* opened due to resource restrictions
* @throws IllegalArgumentException if the buffer size does not represent
* an integral number of sample frames,
* or if <code>format</code> is not fully specified or invalid
* @throws IllegalStateException if the line is already open
* @throws SecurityException if the line cannot be
* opened due to security restrictions
*
* @see #open(AudioFormat)
* @see Line#open
* @see Line#close
* @see Line#isOpen
* @see LineEvent
*/
public void open(AudioFormat format, int bufferSize) throws LineUnavailableException;
/**
* Opens the line with the specified format, causing the line to acquire any
* required system resources and become operational.
*
* <p>
* The implementation chooses a buffer size, which is measured in bytes but
* which encompasses an integral number of sample frames. The buffer size
* that the system has chosen may be queried by subsequently calling
* <code>{@link DataLine#getBufferSize}</code>.
* <p>
* If this operation succeeds, the line is marked as open, and an
* <code>{@link LineEvent.Type#OPEN OPEN}</code> event is dispatched to the
* line's listeners.
* <p>
* Invoking this method on a line which is already open is illegal
* and may result in an <code>IllegalStateException</code>.
* <p>
* Note that some lines, once closed, cannot be reopened. Attempts
* to reopen such a line will always result in a
* <code>LineUnavailableException</code>.
*
* @param format the desired audio format
* @throws LineUnavailableException if the line cannot be
* opened due to resource restrictions
* @throws IllegalArgumentException if <code>format</code>
* is not fully specified or invalid
* @throws IllegalStateException if the line is already open
* @throws SecurityException if the line cannot be
* opened due to security restrictions
*
* @see #open(AudioFormat, int)
* @see Line#open
* @see Line#close
* @see Line#isOpen
* @see LineEvent
*/
public void open(AudioFormat format) throws LineUnavailableException;
/**
* Writes audio data to the mixer via this source data line. The requested
* number of bytes of data are read from the specified array,
* starting at the given offset into the array, and written to the data
* line's buffer. If the caller attempts to write more data than can
* currently be written (see <code>{@link DataLine#available available}</code>),
* this method blocks until the requested amount of data has been written.
* This applies even if the requested amount of data to write is greater
* than the data line's buffer size. However, if the data line is closed,
* stopped, or flushed before the requested amount has been written,
* the method no longer blocks, but returns the number of bytes
* written thus far.
* <p>
* The number of bytes that can be written without blocking can be ascertained
* using the <code>{@link DataLine#available available}</code> method of the
* <code>DataLine</code> interface. (While it is guaranteed that
* this number of bytes can be written without blocking, there is no guarantee
* that attempts to write additional data will block.)
* <p>
* The number of bytes to write must represent an integral number of
* sample frames, such that:
* <br>
* <center><code>[ bytes written ] % [frame size in bytes ] == 0</code></center>
* <br>
* The return value will always meet this requirement. A request to write a
* number of bytes representing a non-integral number of sample frames cannot
* be fulfilled and may result in an <code>IllegalArgumentException</code>.
*
* @param b a byte array containing data to be written to the data line
* @param len the length, in bytes, of the valid data in the array
* (in other words, the requested amount of data to write, in bytes)
* @param off the offset from the beginning of the array, in bytes
* @return the number of bytes actually written
* @throws IllegalArgumentException if the requested number of bytes does
* not represent an integral number of sample frames,
* or if <code>len</code> is negative
* @throws ArrayIndexOutOfBoundsException if <code>off</code> is negative,
* or <code>off+len</code> is greater than the length of the array
* <code>b</code>.
*
* @see TargetDataLine#read
* @see DataLine#available
*/
public int write(byte[] b, int off, int len);
/**
* Obtains the number of sample frames of audio data that can be written to
* the mixer, via this data line, without blocking. Note that the return
* value measures sample frames, not bytes.
* @return the number of sample frames currently available for writing
* @see TargetDataLine#availableRead
*/
//public int availableWrite();
}

View File

@@ -0,0 +1,192 @@
/*
* Copyright (c) 1999, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* A target data line is a type of <code>{@link DataLine}</code> from which
* audio data can be read. The most common example is a data line that gets
* its data from an audio capture device. (The device is implemented as a
* mixer that writes to the target data line.)
* <p>
* Note that the naming convention for this interface reflects the relationship
* between the line and its mixer. From the perspective of an application,
* a target data line may act as a source for audio data.
* <p>
* The target data line can be obtained from a mixer by invoking the
* <code>{@link Mixer#getLine getLine}</code>
* method of <code>Mixer</code> with an appropriate
* <code>{@link DataLine.Info}</code> object.
* <p>
* The <code>TargetDataLine</code> interface provides a method for reading the
* captured data from the target data line's buffer.Applications
* that record audio should read data from the target data line quickly enough
* to keep the buffer from overflowing, which could cause discontinuities in
* the captured data that are perceived as clicks. Applications can use the
* <code>{@link DataLine#available available}</code> method defined in the
* <code>DataLine</code> interface to determine the amount of data currently
* queued in the data line's buffer. If the buffer does overflow,
* the oldest queued data is discarded and replaced by new data.
*
* @author Kara Kytle
* @see Mixer
* @see DataLine
* @see SourceDataLine
* @since 1.3
*/
public interface TargetDataLine extends DataLine {
/**
* Opens the line with the specified format and requested buffer size,
* causing the line to acquire any required system resources and become
* operational.
* <p>
* The buffer size is specified in bytes, but must represent an integral
* number of sample frames. Invoking this method with a requested buffer
* size that does not meet this requirement may result in an
* IllegalArgumentException. The actual buffer size for the open line may
* differ from the requested buffer size. The value actually set may be
* queried by subsequently calling <code>{@link DataLine#getBufferSize}</code>
* <p>
* If this operation succeeds, the line is marked as open, and an
* <code>{@link LineEvent.Type#OPEN OPEN}</code> event is dispatched to the
* line's listeners.
* <p>
* Invoking this method on a line that is already open is illegal
* and may result in an <code>IllegalStateException</code>.
* <p>
* Some lines, once closed, cannot be reopened. Attempts
* to reopen such a line will always result in a
* <code>LineUnavailableException</code>.
*
* @param format the desired audio format
* @param bufferSize the desired buffer size, in bytes.
* @throws LineUnavailableException if the line cannot be
* opened due to resource restrictions
* @throws IllegalArgumentException if the buffer size does not represent
* an integral number of sample frames,
* or if <code>format</code> is not fully specified or invalid
* @throws IllegalStateException if the line is already open
* @throws SecurityException if the line cannot be
* opened due to security restrictions
*
* @see #open(AudioFormat)
* @see Line#open
* @see Line#close
* @see Line#isOpen
* @see LineEvent
*/
public void open(AudioFormat format, int bufferSize) throws LineUnavailableException;
/**
* Opens the line with the specified format, causing the line to acquire any
* required system resources and become operational.
*
* <p>
* The implementation chooses a buffer size, which is measured in bytes but
* which encompasses an integral number of sample frames. The buffer size
* that the system has chosen may be queried by subsequently calling <code>{@link DataLine#getBufferSize}</code>
* <p>
* If this operation succeeds, the line is marked as open, and an
* <code>{@link LineEvent.Type#OPEN OPEN}</code> event is dispatched to the
* line's listeners.
* <p>
* Invoking this method on a line that is already open is illegal
* and may result in an <code>IllegalStateException</code>.
* <p>
* Some lines, once closed, cannot be reopened. Attempts
* to reopen such a line will always result in a
* <code>LineUnavailableException</code>.
*
* @param format the desired audio format
* @throws LineUnavailableException if the line cannot be
* opened due to resource restrictions
* @throws IllegalArgumentException if <code>format</code>
* is not fully specified or invalid
* @throws IllegalStateException if the line is already open
* @throws SecurityException if the line cannot be
* opened due to security restrictions
*
* @see #open(AudioFormat, int)
* @see Line#open
* @see Line#close
* @see Line#isOpen
* @see LineEvent
*/
public void open(AudioFormat format) throws LineUnavailableException;
/**
* Reads audio data from the data line's input buffer. The requested
* number of bytes is read into the specified array, starting at
* the specified offset into the array in bytes. This method blocks until
* the requested amount of data has been read. However, if the data line
* is closed, stopped, drained, or flushed before the requested amount has
* been read, the method no longer blocks, but returns the number of bytes
* read thus far.
* <p>
* The number of bytes that can be read without blocking can be ascertained
* using the <code>{@link DataLine#available available}</code> method of the
* <code>DataLine</code> interface. (While it is guaranteed that
* this number of bytes can be read without blocking, there is no guarantee
* that attempts to read additional data will block.)
* <p>
* The number of bytes to be read must represent an integral number of
* sample frames, such that:
* <br>
* <center><code>[ bytes read ] % [frame size in bytes ] == 0</code></center>
* <br>
* The return value will always meet this requirement. A request to read a
* number of bytes representing a non-integral number of sample frames cannot
* be fulfilled and may result in an IllegalArgumentException.
*
* @param b a byte array that will contain the requested input data when
* this method returns
* @param off the offset from the beginning of the array, in bytes
* @param len the requested number of bytes to read
* @return the number of bytes actually read
* @throws IllegalArgumentException if the requested number of bytes does
* not represent an integral number of sample frames.
* or if <code>len</code> is negative.
* @throws ArrayIndexOutOfBoundsException if <code>off</code> is negative,
* or <code>off+len</code> is greater than the length of the array
* <code>b</code>.
*
* @see SourceDataLine#write
* @see DataLine#available
*/
public int read(byte[] b, int off, int len);
/**
* Obtains the number of sample frames of audio data that can be read from
* the target data line without blocking. Note that the return value
* measures sample frames, not bytes.
* @return the number of sample frames currently available for reading
* @see SourceDataLine#availableWrite
*/
//public int availableRead();
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled;
/**
* An <code>UnsupportedAudioFileException</code> is an exception indicating that an
* operation failed because a file did not contain valid data of a recognized file
* type and format.
*
* @author Kara Kytle
* @since 1.3
*/
/*
* An <code>UnsupportedAudioFileException</code> is an exception indicating that an
* operation failed because a file did not contain valid data of a recognized file
* type and format.
*
* @author Kara Kytle
*/
public class UnsupportedAudioFileException extends Exception {
/**
* Constructs a <code>UnsupportedAudioFileException</code> that has
* <code>null</code> as its error detail message.
*/
public UnsupportedAudioFileException() {
super();
}
/**
* Constructs a <code>UnsupportedAudioFileException</code> that has
* the specified detail message.
*
* @param message a string containing the error detail message
*/
public UnsupportedAudioFileException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled.spi;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
* Provider for audio file reading services. Classes providing concrete
* implementations can parse the format information from one or more types of
* audio file, and can produce audio input streams from files of these types.
*
* @author Kara Kytle
* @since 1.3
*/
public abstract class AudioFileReader {
/**
* Obtains the audio file format of the input stream provided. The stream must
* point to valid audio file data. In general, audio file readers may
* need to read some data from the stream before determining whether they
* support it. These parsers must
* be able to mark the stream, read enough data to determine whether they
* support the stream, and, if not, reset the stream's read pointer to its original
* position. If the input stream does not support this, this method may fail
* with an <code>IOException</code>.
* @param stream the input stream from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the stream does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
* @see InputStream#markSupported
* @see InputStream#mark
*/
public abstract AudioFileFormat getAudioFileFormat(InputStream stream) throws UnsupportedAudioFileException, IOException;
/**
* Obtains the audio file format of the URL provided. The URL must
* point to valid audio file data.
* @param url the URL from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the URL does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public abstract AudioFileFormat getAudioFileFormat(URL url) throws UnsupportedAudioFileException, IOException;
/**
* Obtains the audio file format of the <code>File</code> provided. The <code>File</code> must
* point to valid audio file data.
* @param file the <code>File</code> from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the <code>File</code> does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public abstract AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFileException, IOException;
/**
* Obtains an audio input stream from the input stream provided. The stream must
* point to valid audio file data. In general, audio file readers may
* need to read some data from the stream before determining whether they
* support it. These parsers must
* be able to mark the stream, read enough data to determine whether they
* support the stream, and, if not, reset the stream's read pointer to its original
* position. If the input stream does not support this, this method may fail
* with an <code>IOException</code>.
* @param stream the input stream from which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data contained
* in the input stream.
* @throws UnsupportedAudioFileException if the stream does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
* @see InputStream#markSupported
* @see InputStream#mark
*/
public abstract AudioInputStream getAudioInputStream(InputStream stream) throws UnsupportedAudioFileException, IOException;
/**
* Obtains an audio input stream from the URL provided. The URL must
* point to valid audio file data.
* @param url the URL for which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data pointed
* to by the URL
* @throws UnsupportedAudioFileException if the URL does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public abstract AudioInputStream getAudioInputStream(URL url) throws UnsupportedAudioFileException, IOException;
/**
* Obtains an audio input stream from the <code>File</code> provided. The <code>File</code> must
* point to valid audio file data.
* @param file the <code>File</code> for which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data pointed
* to by the File
* @throws UnsupportedAudioFileException if the <code>File</code> does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public abstract AudioInputStream getAudioInputStream(File file) throws UnsupportedAudioFileException, IOException;
}

View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 1999, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled.spi;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
/**
* Provider for audio file writing services. Classes providing concrete
* implementations can write one or more types of audio file from an audio
* stream.
*
* @author Kara Kytle
* @since 1.3
*/
public abstract class AudioFileWriter {
/**
* Obtains the file types for which file writing support is provided by this
* audio file writer.
* @return array of file types. If no file types are supported,
* an array of length 0 is returned.
*/
public abstract AudioFileFormat.Type[] getAudioFileTypes();
/**
* Indicates whether file writing support for the specified file type is provided
* by this audio file writer.
* @param fileType the file type for which write capabilities are queried
* @return <code>true</code> if the file type is supported,
* otherwise <code>false</code>
*/
public boolean isFileTypeSupported(AudioFileFormat.Type fileType) {
AudioFileFormat.Type types[] = getAudioFileTypes();
for(int i=0; i<types.length; i++) {
if( fileType.equals( types[i] ) ) {
return true;
}
}
return false;
}
/**
* Obtains the file types that this audio file writer can write from the
* audio input stream specified.
* @param stream the audio input stream for which audio file type support
* is queried
* @return array of file types. If no file types are supported,
* an array of length 0 is returned.
*/
public abstract AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream stream);
/**
* Indicates whether an audio file of the type specified can be written
* from the audio input stream indicated.
* @param fileType file type for which write capabilities are queried
* @param stream for which file writing support is queried
* @return <code>true</code> if the file type is supported for this audio input stream,
* otherwise <code>false</code>
*/
public boolean isFileTypeSupported(AudioFileFormat.Type fileType, AudioInputStream stream) {
AudioFileFormat.Type types[] = getAudioFileTypes( stream );
for(int i=0; i<types.length; i++) {
if( fileType.equals( types[i] ) ) {
return true;
}
}
return false;
}
/**
* Writes a stream of bytes representing an audio file of the file type
* indicated to the output stream provided. Some file types require that
* the length be written into the file header, and cannot be written from
* start to finish unless the length is known in advance. An attempt
* to write such a file type will fail with an IOException if the length in
* the audio file format is
* {@link javax.sound.sampled.AudioSystem#NOT_SPECIFIED AudioSystem.NOT_SPECIFIED}.
* @param stream the audio input stream containing audio data to be
* written to the output stream
* @param fileType file type to be written to the output stream
* @param out stream to which the file data should be written
* @return the number of bytes written to the output stream
* @throws IOException if an I/O exception occurs
* @throws IllegalArgumentException if the file type is not supported by
* the system
* @see #isFileTypeSupported(AudioFileFormat.Type, AudioInputStream)
* @see #getAudioFileTypes
*/
public abstract int write(AudioInputStream stream, AudioFileFormat.Type fileType, OutputStream out) throws IOException;
/**
* Writes a stream of bytes representing an audio file of the file format
* indicated to the external file provided.
* @param stream the audio input stream containing audio data to be
* written to the file
* @param fileType file type to be written to the file
* @param out external file to which the file data should be written
* @return the number of bytes written to the file
* @throws IOException if an I/O exception occurs
* @throws IllegalArgumentException if the file format is not supported by
* the system
* @see #isFileTypeSupported
* @see #getAudioFileTypes
*/
public abstract int write(AudioInputStream stream, AudioFileFormat.Type fileType, File out) throws IOException;
}

View File

@@ -0,0 +1,200 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled.spi;
import java.io.InputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
/**
* A format conversion provider provides format conversion services
* from one or more input formats to one or more output formats.
* Converters include codecs, which encode and/or decode audio data,
* as well as transcoders, etc. Format converters provide methods for
* determining what conversions are supported and for obtaining an audio
* stream from which converted data can be read.
* <p>
* The source format represents the format of the incoming
* audio data, which will be converted.
* <p>
* The target format represents the format of the processed, converted
* audio data. This is the format of the data that can be read from
* the stream returned by one of the <code>getAudioInputStream</code> methods.
*
* @author Kara Kytle
* @since 1.3
*/
public abstract class FormatConversionProvider {
// NEW METHODS
/**
* Obtains the set of source format encodings from which format
* conversion services are provided by this provider.
* @return array of source format encodings. If for some reason provider
* does not provide any conversion services, an array of length 0 is
* returned.
*/
public abstract AudioFormat.Encoding[] getSourceEncodings();
/**
* Obtains the set of target format encodings to which format
* conversion services are provided by this provider.
* @return array of target format encodings. If for some reason provider
* does not provide any conversion services, an array of length 0 is
* returned.
*/
public abstract AudioFormat.Encoding[] getTargetEncodings();
/**
* Indicates whether the format converter supports conversion from the
* specified source format encoding.
* @param sourceEncoding the source format encoding for which support is queried
* @return <code>true</code> if the encoding is supported, otherwise <code>false</code>
*/
public boolean isSourceEncodingSupported(AudioFormat.Encoding sourceEncoding){
AudioFormat.Encoding sourceEncodings[] = getSourceEncodings();
for(int i=0; i<sourceEncodings.length; i++) {
if( sourceEncoding.equals( sourceEncodings[i]) ) {
return true;
}
}
return false;
}
/**
* Indicates whether the format converter supports conversion to the
* specified target format encoding.
* @param targetEncoding the target format encoding for which support is queried
* @return <code>true</code> if the encoding is supported, otherwise <code>false</code>
*/
public boolean isTargetEncodingSupported(AudioFormat.Encoding targetEncoding){
AudioFormat.Encoding targetEncodings[] = getTargetEncodings();
for(int i=0; i<targetEncodings.length; i++) {
if( targetEncoding.equals( targetEncodings[i]) ) {
return true;
}
}
return false;
}
/**
* Obtains the set of target format encodings supported by the format converter
* given a particular source format.
* If no target format encodings are supported for this source format,
* an array of length 0 is returned.
* @param sourceFormat format of the incoming data
* @return array of supported target format encodings.
*/
public abstract AudioFormat.Encoding[] getTargetEncodings(AudioFormat sourceFormat);
/**
* Indicates whether the format converter supports conversion to a particular encoding
* from a particular format.
* @param targetEncoding desired encoding of the outgoing data
* @param sourceFormat format of the incoming data
* @return <code>true</code> if the conversion is supported, otherwise <code>false</code>
*/
public boolean isConversionSupported(AudioFormat.Encoding targetEncoding, AudioFormat sourceFormat){
AudioFormat.Encoding targetEncodings[] = getTargetEncodings(sourceFormat);
for(int i=0; i<targetEncodings.length; i++) {
if( targetEncoding.equals( targetEncodings[i]) ) {
return true;
}
}
return false;
}
/**
* Obtains the set of target formats with the encoding specified
* supported by the format converter
* If no target formats with the specified encoding are supported
* for this source format, an array of length 0 is returned.
* @param targetEncoding desired encoding of the stream after processing
* @param sourceFormat format of the incoming data
* @return array of supported target formats.
*/
public abstract AudioFormat[] getTargetFormats(AudioFormat.Encoding targetEncoding, AudioFormat sourceFormat);
/**
* Indicates whether the format converter supports conversion to one
* particular format from another.
* @param targetFormat desired format of outgoing data
* @param sourceFormat format of the incoming data
* @return <code>true</code> if the conversion is supported, otherwise <code>false</code>
*/
public boolean isConversionSupported(AudioFormat targetFormat, AudioFormat sourceFormat){
AudioFormat targetFormats[] = getTargetFormats( targetFormat.getEncoding(), sourceFormat );
for(int i=0; i<targetFormats.length; i++) {
if( targetFormat.matches( targetFormats[i] ) ) {
return true;
}
}
return false;
}
/**
* Obtains an audio input stream with the specified encoding from the given audio
* input stream.
* @param targetEncoding desired encoding of the stream after processing
* @param sourceStream stream from which data to be processed should be read
* @return stream from which processed data with the specified target encoding may be read
* @throws IllegalArgumentException if the format combination supplied is
* not supported.
*/
public abstract AudioInputStream getAudioInputStream(AudioFormat.Encoding targetEncoding, AudioInputStream sourceStream);
/**
* Obtains an audio input stream with the specified format from the given audio
* input stream.
* @param targetFormat desired data format of the stream after processing
* @param sourceStream stream from which data to be processed should be read
* @return stream from which processed data with the specified format may be read
* @throws IllegalArgumentException if the format combination supplied is
* not supported.
*/
public abstract AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream sourceStream);
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 1999, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sound.sampled.spi;
import javax.sound.sampled.Mixer;
/**
* A provider or factory for a particular mixer type.
* This mechanism allows the implementation to determine
* how resources are managed in creation / management of
* a mixer.
*
* @author Kara Kytle
* @since 1.3
*/
public abstract class MixerProvider {
/**
* Indicates whether the mixer provider supports the mixer represented by
* the specified mixer info object.
* <p>
* The full set of mixer info objects that represent the mixers supported
* by this {@code MixerProvider} may be obtained
* through the {@code getMixerInfo} method.
*
* @param info an info object that describes the mixer for which support is queried
* @return {@code true} if the specified mixer is supported,
* otherwise {@code false}
* @see #getMixerInfo()
*/
public boolean isMixerSupported(Mixer.Info info) {
Mixer.Info infos[] = getMixerInfo();
for(int i=0; i<infos.length; i++){
if( info.equals( infos[i] ) ) {
return true;
}
}
return false;
}
/**
* Obtains the set of info objects representing the mixer
* or mixers provided by this MixerProvider.
* <p>
* The {@code isMixerSupported} method returns {@code true}
* for all the info objects returned by this method.
* The corresponding mixer instances for the info objects
* are returned by the {@code getMixer} method.
*
* @return a set of mixer info objects
* @see #getMixer(javax.sound.sampled.Mixer.Info) getMixer(Mixer.Info)
* @see #isMixerSupported(javax.sound.sampled.Mixer.Info) isMixerSupported(Mixer.Info)
*/
public abstract Mixer.Info[] getMixerInfo();
/**
* Obtains an instance of the mixer represented by the info object.
* <p>
* The full set of the mixer info objects that represent the mixers
* supported by this {@code MixerProvider} may be obtained
* through the {@code getMixerInfo} method.
* Use the {@code isMixerSupported} method to test whether
* this {@code MixerProvider} supports a particular mixer.
*
* @param info an info object that describes the desired mixer
* @return mixer instance
* @throws IllegalArgumentException if the info object specified does not
* match the info object for a mixer supported by this MixerProvider.
* @see #getMixerInfo()
* @see #isMixerSupported(javax.sound.sampled.Mixer.Info) isMixerSupported(Mixer.Info)
*/
public abstract Mixer getMixer(Mixer.Info info);
}