1. /*
  2. * @(#)FloatControl.java 1.16 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.sound.sampled;
  8. /**
  9. * A <code>FloatControl</code> object provides control over a range of
  10. * floating-point values. Float controls are often
  11. * represented in graphical user interfaces by continuously
  12. * adjustable objects such as sliders or rotary knobs. Concrete subclasses
  13. * of <code>FloatControl</code> implement controls, such as gain and pan, that
  14. * affect a line's audio signal in some way that an application can manipulate.
  15. * The <code>{@link FloatControl.Type}</code>
  16. * inner class provides static instances of types that are used to
  17. * identify some common kinds of float control.
  18. * <p>
  19. * The <code>FloatControl</code> abstract class provides methods to set and get
  20. * the control's current floating-point value. Other methods obtain the possible
  21. * range of values and the control's resolution (the smallest increment between
  22. * returned values). Some float controls allow ramping to a
  23. * new value over a specified period of time. <code>FloatControl</code> also
  24. * includes methods that return string labels for the minimum, maximum, and midpoint
  25. * positions of the control.
  26. *
  27. * @see Line#getControls
  28. * @see Line#isControlSupported
  29. *
  30. * @author David Rivas
  31. * @author Kara Kytle
  32. * @version 1.16, 03/12/19
  33. * @since 1.3
  34. */
  35. public abstract class FloatControl extends Control {
  36. // INSTANCE VARIABLES
  37. // FINAL VARIABLES
  38. /**
  39. * The minimum supported value.
  40. */
  41. private float minimum;
  42. /**
  43. * The maximum supported value.
  44. */
  45. private float maximum;
  46. /**
  47. * The control's precision.
  48. */
  49. private float precision;
  50. /**
  51. * The smallest time increment in which a value change
  52. * can be effected during a value shift, in microseconds.
  53. */
  54. private int updatePeriod;
  55. /**
  56. * A label for the units in which the control values are expressed,
  57. * such as "dB" for decibels.
  58. */
  59. private final String units;
  60. /**
  61. * A label for the minimum value, such as "Left."
  62. */
  63. private final String minLabel;
  64. /**
  65. * A label for the maximum value, such as "Right."
  66. */
  67. private final String maxLabel;
  68. /**
  69. * A label for the mid-point value, such as "Center."
  70. */
  71. private final String midLabel;
  72. // STATE VARIABLES
  73. /**
  74. * The current value.
  75. */
  76. private float value;
  77. // CONSTRUCTORS
  78. /**
  79. * Constructs a new float control object with the given parameters
  80. *
  81. * @param type the kind of control represented by this float control object
  82. * @param minimum the smallest value permitted for the control
  83. * @param maximum the largest value permitted for the control
  84. * @param precision the resolution or granularity of the control.
  85. * This is the size of the increment between discrete valid values.
  86. * @param updatePeriod the smallest time interval, in microseconds, over which the control
  87. * can change from one discrete value to the next during a {@link #shift(float,float,int) shift}
  88. * @param initialValue the value that the control starts with when constructed
  89. * @param units the label for the units in which the control's values are expressed,
  90. * such as "dB" or "frames per second"
  91. * @param minLabel the label for the minimum value, such as "Left" or "Off"
  92. * @param midLabel the label for the midpoint value, such as "Center" or "Default"
  93. * @param maxLabel the label for the maximum value, such as "Right" or "Full"
  94. */
  95. protected FloatControl(Type type, float minimum, float maximum,
  96. float precision, int updatePeriod, float initialValue,
  97. String units, String minLabel, String midLabel, String maxLabel) {
  98. super(type);
  99. this.minimum = minimum;
  100. this.maximum = maximum;
  101. this.precision = precision;
  102. this.updatePeriod = updatePeriod;
  103. this.value = initialValue;
  104. this.units = units;
  105. this.minLabel = ( (minLabel == null) ? "" : minLabel);
  106. this.midLabel = ( (midLabel == null) ? "" : midLabel);
  107. this.maxLabel = ( (maxLabel == null) ? "" : maxLabel);
  108. }
  109. /**
  110. * Constructs a new float control object with the given parameters.
  111. * The labels for the minimum, maximum, and mid-point values are set
  112. * to zero-length strings.
  113. *
  114. * @param type the kind of control represented by this float control object
  115. * @param minimum the smallest value permitted for the control
  116. * @param maximum the largest value permitted for the control
  117. * @param precision the resolution or granularity of the control.
  118. * This is the size of the increment between discrete valid values.
  119. * @param updatePeriod the smallest time interval, in microseconds, over which the control
  120. * can change from one discrete value to the next during a {@link #shift(float,float,int) shift}
  121. * @param initialValue the value that the control starts with when constructed
  122. * @param units the label for the units in which the control's values are expressed,
  123. * such as "dB" or "frames per second"
  124. */
  125. protected FloatControl(Type type, float minimum, float maximum,
  126. float precision, int updatePeriod, float initialValue, String units) {
  127. this(type, minimum, maximum, precision, updatePeriod, initialValue, units, "", "", "");
  128. }
  129. // METHODS
  130. /**
  131. * Sets the current value for the control. The default implementation
  132. * simply sets the value as indicated. If the value indicated is greater
  133. * than the maximum value, or smaller than the minimum value, an
  134. * IllegalArgumentException is thrown.
  135. * Some controls require that their line be open before they can be affected
  136. * by setting a value.
  137. * @param newValue desired new value
  138. * @throws IllegalArgumentException if the value indicated does not fall
  139. * within the allowable range
  140. */
  141. public void setValue(float newValue) {
  142. if (newValue > maximum) {
  143. throw new IllegalArgumentException("Requested value " + newValue + " exceeds allowable maximum value " + maximum + ".");
  144. }
  145. if (newValue < minimum) {
  146. throw new IllegalArgumentException("Requested value " + newValue + " smaller than allowable minimum value " + minimum + ".");
  147. }
  148. value = newValue;
  149. }
  150. /**
  151. * Obtains this control's current value.
  152. * @return the current value
  153. */
  154. public float getValue() {
  155. return value;
  156. }
  157. /**
  158. * Obtains the maximum value permitted.
  159. * @return the maximum allowable value
  160. */
  161. public float getMaximum() {
  162. return maximum;
  163. }
  164. /**
  165. * Obtains the minimum value permitted.
  166. * @return the minimum allowable value
  167. */
  168. public float getMinimum() {
  169. return minimum;
  170. }
  171. /**
  172. * Obtains the label for the units in which the control's values are expressed,
  173. * such as "dB" or "frames per second."
  174. * @return the units label, or a zero-length string if no label
  175. */
  176. public String getUnits() {
  177. return units;
  178. }
  179. /**
  180. * Obtains the label for the minimum value, such as "Left" or "Off."
  181. * @return the minimum value label, or a zero-length string if no label * has been set
  182. */
  183. public String getMinLabel() {
  184. return minLabel;
  185. }
  186. /**
  187. * Obtains the label for the mid-point value, such as "Center" or "Default."
  188. * @return the mid-point value label, or a zero-length string if no label * has been set
  189. */
  190. public String getMidLabel() {
  191. return midLabel;
  192. }
  193. /**
  194. * Obtains the label for the maximum value, such as "Right" or "Full."
  195. * @return the maximum value label, or a zero-length string if no label * has been set
  196. */
  197. public String getMaxLabel() {
  198. return maxLabel;
  199. }
  200. /**
  201. * Obtains the resolution or granularity of the control, in the units
  202. * that the control measures.
  203. * The precision is the size of the increment between discrete valid values
  204. * for this control, over the set of supported floating-point values.
  205. * @return the control's precision
  206. */
  207. public float getPrecision() {
  208. return precision;
  209. }
  210. /**
  211. * Obtains the smallest time interval, in microseconds, over which the control's value can
  212. * change during a shift. The update period is the inverse of the frequency with which
  213. * the control updates its value during a shift. If the implementation does not support value shifting over
  214. * time, it should set the control's value to the final value immediately
  215. * and return -1 from this method.
  216. *
  217. * @return update period in microseconds, or -1 if shifting over time is unsupported
  218. * @see #shift
  219. */
  220. public int getUpdatePeriod() {
  221. return updatePeriod;
  222. }
  223. /**
  224. * Changes the control value from the initial value to the final
  225. * value linearly over the specified time period, specified in microseconds.
  226. * This method returns without blocking; it does not wait for the shift
  227. * to complete. An implementation should complete the operation within the time
  228. * specified. The default implementation simply changes the value
  229. * to the final value immediately.
  230. *
  231. * @param from initial value at the beginning of the shift
  232. * @param to final value after the shift
  233. * @param microseconds maximum duration of the shift in microseconds
  234. *
  235. * @see #getUpdatePeriod
  236. */
  237. public void shift(float from, float to, int microseconds) {
  238. setValue(to);
  239. }
  240. // ABSTRACT METHOD IMPLEMENTATIONS: CONTROL
  241. /**
  242. * Provides a string representation of the control
  243. * @return a string description
  244. */
  245. public String toString() {
  246. return new String(getType() + " with current value: " + getValue() + " " + units +
  247. " (range: " + minimum + " - " + maximum + ")");
  248. }
  249. // INNER CLASSES
  250. /**
  251. * An instance of the <code>FloatControl.Type</code> inner class identifies one kind of
  252. * float control. Static instances are provided for the
  253. * common types.
  254. *
  255. * @author Kara Kytle
  256. * @version 1.16, 03/12/19
  257. * @since 1.3
  258. */
  259. public static class Type extends Control.Type {
  260. // TYPE DEFINES
  261. // GAIN TYPES
  262. /**
  263. * Represents a control for the overall gain on a line.
  264. * <p>
  265. * Gain is a quantity in decibels (dB) that is added to the intrinsic
  266. * decibel level of the audio signal--that is, the level of
  267. * the signal before it is altered by the gain control. A positive
  268. * gain amplifies (boosts) the signal's volume, and a negative gain
  269. * attenuates (cuts) it.
  270. * The gain setting defaults to a value of 0.0 dB, meaning the signal's
  271. * loudness is unaffected. Note that gain measures dB, not amplitude.
  272. * The relationship between a gain in decibels and the corresponding
  273. * linear amplitude multiplier is:
  274. *
  275. *<CENTER><CODE> linearScalar = pow(10.0, gainDB/20.0) </CODE></CENTER>
  276. * <p>
  277. * The <code>FloatControl</code> class has methods to impose a maximum and
  278. * minimum allowable value for gain. However, because an audio signal might
  279. * already be at a high amplitude, the maximum setting does not guarantee
  280. * that the signal will be undistorted when the gain is applied to it (unless
  281. * the maximum is zero or negative). To avoid numeric overflow from excessively
  282. * large gain settings, a gain control can implement
  283. * clipping, meaning that the signal's amplitude will be limited to the maximum
  284. * value representable by its audio format, instead of wrapping around.
  285. * <p>
  286. * These comments apply to gain controls in general, not just master gain controls.
  287. * A line can have more than one gain control. For example, a mixer (which is
  288. * itself a line) might have a master gain control, an auxiliary return control,
  289. * a reverb return control, and, on each of its source lines, an individual aux
  290. * send and reverb send.
  291. *
  292. * @see #AUX_SEND
  293. * @see #AUX_RETURN
  294. * @see #REVERB_SEND
  295. * @see #REVERB_RETURN
  296. * @see #VOLUME
  297. */
  298. public static final Type MASTER_GAIN = new Type("Master Gain");
  299. /**
  300. * Represents a control for the auxiliary send gain on a line.
  301. *
  302. * @see #MASTER_GAIN
  303. * @see #AUX_RETURN
  304. */
  305. public static final Type AUX_SEND = new Type("AUX Send");
  306. /**
  307. * Represents a control for the auxiliary return gain on a line.
  308. *
  309. * @see #MASTER_GAIN
  310. * @see #AUX_SEND
  311. */
  312. public static final Type AUX_RETURN = new Type("AUX Return");
  313. /**
  314. * Represents a control for the pre-reverb gain on a line.
  315. * This control may be used to affect how much
  316. * of a line's signal is directed to a mixer's internal reverberation unit.
  317. *
  318. * @see #MASTER_GAIN
  319. * @see #REVERB_RETURN
  320. * @see EnumControl.Type#REVERB
  321. */
  322. public static final Type REVERB_SEND = new Type("Reverb Send");
  323. /**
  324. * Represents a control for the post-reverb gain on a line.
  325. * This control may be used to control the relative amplitude
  326. * of the signal returned from an internal reverberation unit.
  327. *
  328. * @see #MASTER_GAIN
  329. * @see #REVERB_SEND
  330. */
  331. public static final Type REVERB_RETURN = new Type("Reverb Return");
  332. // VOLUME
  333. /**
  334. * Represents a control for the volume on a line.
  335. */
  336. /*
  337. * $$kk: 08.30.99: ISSUE: what units? linear or dB?
  338. */
  339. public static final Type VOLUME = new Type("Volume");
  340. // PAN
  341. /**
  342. * Represents a control for the relative pan (left-right positioning)
  343. * of the signal. The signal may be mono; the pan setting affects how
  344. * it is distributed by the mixer in a stereo mix. The valid range of values is -1.0
  345. * (left channel only) to 1.0 (right channel
  346. * only). The default is 0.0 (centered).
  347. *
  348. * @see #BALANCE
  349. */
  350. public static final Type PAN = new Type("Pan");
  351. // BALANCE
  352. /**
  353. * Represents a control for the relative balance of a stereo signal
  354. * between two stereo speakers. The valid range of values is -1.0 (left channel only) to 1.0 (right channel
  355. * only). The default is 0.0 (centered).
  356. *
  357. * @see #PAN
  358. */
  359. public static final Type BALANCE = new Type("Balance");
  360. // SAMPLE RATE
  361. /**
  362. * Represents a control that changes the sample rate of audio playback. The net effect
  363. * of changing the sample rate depends on the relationship between
  364. * the media's natural rate and the rate that is set via this control.
  365. * The natural rate is the sample rate that is specified in the data line's
  366. * <code>AudioFormat</code> object. For example, if the natural rate
  367. * of the media is 11025 samples per second and the sample rate is set
  368. * to 22050 samples per second, the media will play back at twice the
  369. * normal speed.
  370. * <p>
  371. * Changing the sample rate with this control does not affect the data line's
  372. * audio format. Also note that whenever you change a sound's sample rate, a
  373. * change in the sound's pitch results. For example, doubling the sample
  374. * rate has the effect of doubling the frequencies in the sound's spectrum,
  375. * which raises the pitch by an octave.
  376. */
  377. public static final Type SAMPLE_RATE = new Type("Sample Rate");
  378. // CONSTRUCTOR
  379. /**
  380. * Constructs a new float control type.
  381. * @param name the name of the new float control type
  382. */
  383. protected Type(String name) {
  384. super(name);
  385. }
  386. } // class Type
  387. } // class FloatControl