GitHub - philfrei/AudioCue-maven: A Java audio-playback class, modeled on javax....
source link: https://github.com/philfrei/AudioCue-maven
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
AudioCue-maven
AudioCue is a Java audio-playback class, modeled on javax.sound.sampled.Clip, enhanced with concurrent playback and with dynamic handling of volume, pan and frequency. Included is a mixer that can be optionally used to merge the output of multiple AudioCues into a single line out.
The project is now published on Maven Central. Unit tests have been added, and more rigorous API documentation has been written. Over the course of making these changes, some errors and shortcomings were uncovered and have been corrected. The changes are extensive enough that this project will have a starting release version of 2.0.0. The previous version will no longer be maintained.
The best way to make use of the AudioCue class is use the Maven build tool, and list AudioCue as a dependency. To use AudioCue as a Maven dependency, add the following to your project's POM file.
<dependencies>
<dependency>
<groupId>com.adonax</groupId>
<artifactId>audiocue</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
When used in this way, source code and Javadocs documentation will automatically be linked.
Another option is to fork this project and clone it to a development environment. From there, executing Maven's install command will put the library into the local Maven repository. Or, you can directly make use of the jar file that is created in the /target subdirectory via the package command by adding this jar file to your project's classpath. Also, since there are only a few files, you can consider simply copying these files directly into your project. Just be sure, if you do, to edit the package lines of the files to appropriately reflect their new file locations.
Usage
Basic playback (for "fire-and-forget" use)
// Recommended: define as an instance variable.
AudioCue myAudioCue;
// Recommended: preload one time only
// This example assumes "myAudio.wav" is located in src/main/resources folder
// of a Maven project
URL url = this.getClass().getResource("/myAudio.wav");
// This example allows up to 4 concurrent playbacks
AudioCue myAudioCue = AudioCue.makeStereoCue(url, 4);
myAudioCue.open();
// end of preloading steps
// Recommended: the play() method should be called on a preloaded
// instance variable separately from preloading. Reloading or reopening
// prior to each play() will likely add latency for no practical purpose.
myAudioCue.play();
// see API for parameters to override default vol, pan, speed
// release resources when sound is no longer needed
myAudioCue.close();
Usage: dynamic controls
To dynamically change the playback of a sound, we need to identify
the playback instance. Each playback instance has its own identifier,
an int
ranging from 0 to the number of configured concurrent instances minus one.
These identifiers are initially held in a pool of available instances.
If the pool has not been depleted, an identifier is obtained from the pool
at the moment of playback as follows:
int handle = myAudioCue.play();
One can also obtain an identifier from the pool of available instances as follows:
int handle = myAudioCue.obtainInstance();
A specific instance can be started, stopped, or released by including the instance identifier as an argument:
myAudioCue.start(handle);
myAudioCue.stop(handle);
myAudioCue.releaseInstance(handle);
Releasing returns the instance identifier to the pool of available instances.
An important distinction exists between instances obtained from one of the
play
methods versus the obtainInstance()
method.
The default value of the property recycleWhenDone
for an instance
obtained from play()
is true
. Thus, when playback completes, the
identifier will be returned to the pool of available instances.
An instance arising from obtainInstance()
has the property recycleWhenDone
set to false
. In this case, when playback completes, the instance identifier
is not returned to the pool of available instances, and the instance remains
receptive to additional commands. In this case, after playing through to the
end, the frame position will be set to the end of the audio-data file, and,
like a Clip
that has played through, will require repositioning and restarting
for further plays.
Properties that can be altered for an instance include the following:
//*volume*:
myAudioCue.setVolume(handle, value); // double ranging from 0 (silent)
// to 1 (full volume)
//*panning*:
myAudioCue.setPan(handle, value); // double ranging from -1 (full left)
// to 1 (full right)
//*speed of playback*:
myAudioCue.setSpeed(handle, value); // value is a factor that is
// multiplied against the normal playback rate, e.g.,
// 2 will double playback speed, 0.5 will halve it
//*position* (cannot be changed while instance is playing):
myAudioCue.setFramePosition(handle, value); // position in frames
myAudioCue.setMillisecondPosition(handle, value); // position in milliseconds
myAudioCue.setsetFractionalPosition(handle, value);
// value is a decimal fraction of the cue length
// where 0 = start, 1 = end
//*other*:
myAudioCue.setRecyleWhenDone(handle, value); // boolean
myAudioCue.setLooping(handle, value); // number of additional times the cue will replay
// -1 = infinite looping
Usage: output configuration
Output configuration occurs within the AudioCue's open
methods. The
default configuration employs javax.sound.sampled.AudioSystem's default
Mixer
and a SourceDataLine
set with a 1024-frame buffer and the highest
thread priority. A high thread priority should not affect performance of
the rest of an application, as audio threads normally spend the vast majority
of their time in a blocked state. The buffer size can be set to
optimize the balance between latency and dropouts. Incidents of dropouts
are usually lessened by increasing the buffer size.
You can override the defaults by using an alternate form of the open()
method. For example:
myAudioCue.open(mixer, bufferFrames, threadPriority);
Each AudioCue
can have its own configuration, and will output on its own SourceDataLine
line.
Usage: Outputting via AudioMixer
Most operating systems will support numerous concurrently playing SourceDataLine
streams. But if desired, the streams can be merged into a single output line using
AudioMixer
, which is part of this package. This is accomplished by providing an
AudioMixer
instance as an argument to the AudioCue
open() method:
myAudioCue.open(myAudioMixer);
Internally, this method adds the AudioCue
to the AudioMixer
using the interface
AudioMixerTrack. If an AudioCue
is a track on an AudioMixer
, the AudioCue
method close() will automatically remove the track from the AudioMixer
.
myAudioCue.close();
The AudioMixer
is configured, upon instantiation, with a default
javax.sound.sampled.Mixer
, with a buffer size of 8192 frames, and
with the highest thread priority. Alternate values can be provided
at instantiation.
Any AudioCue
routed through an AudioMixer
will use the
AudioMixer's configuration properties. Pending AudioMixer
additions and removals are handled automatically at the start of
each buffer iteration.
In the following somewhat artificial example, we create and start an
AudioMixer
, add an AudioCue
track, play the cue, then shut it all down.
AudioMixer audioMixer = new AudioMixer();
audioMixer.start();
// At this point, AudioMixer will create and start a runnable and will
// actively output 'silence' (zero values) on its SourceDataLine.
URL url = this.getClass().getResource("myAudio.wav");
AudioCue myAudioCue = AudioCue.makeStereoCue(url, 1);
myAudioCue.open(mixer);
// The open method automatically adds the AudioCue to
// the AudioMixer.
myAudioCue.play();
Thread.sleep(2000); // For purposes of the demo only, to hold the program open to give the AudioCue time
// to play to completion (assumes cue is shorter than 2 seconds).
myAudioCue.close(); // will remove AudioCue from the mix
audioMixer.stop(); // AudioMixer will stop outputting and will
// close the runnable in an 'orderly' manner.
Reminder, this is an artificial example: best practice is to initialize and
open an AudioCue
only once, and to then reuse the AudioCue
for multiple playbacks.
Also, this example uses Thread.sleep()
to prevent the program from advancing and
closing before the cue finishes playing. The reason for this is that AudioCue
launches
a daemon thread internally for playback, so a playing instance will not prevent a
program from closing once all the program instructions are completed. Unlike this example,
an AudioCue
is more typically called by a GUI that remains open, or from a long-running
program, and is well able to complete playing without the program closing. In that more
usual case, pausing the thread that has the play() method is quite unnecessary.
Usage: Additional examples and test files
Additional examples and test files can be found in the accompanying project audiocue-demo.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK