/* * 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 FloatControl 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 FloatControl implement controls, such as gain and pan, that * affect a line's audio signal in some way that an application can manipulate. * The {@link FloatControl.Type} * inner class provides static instances of types that are used to * identify some common kinds of float control. *

* The FloatControl 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. FloatControl 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 FloatControl.Type 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. *

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

linearScalar = pow(10.0, gainDB/20.0)
*

* The FloatControl 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. *

* 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 * AudioFormat 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. *

* 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