| /* |
| * 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 |