📄 javastreamingaudioplayer.java
字号:
} } /** * Returns the current volume. * * @return the current volume (between 0 and 1) */ public float getVolume() { return volume; } /** * Sets the current volume. * * @param volume the current volume (between 0 and 1) */ public void setVolume(float volume) { if (volume > 1.0f) { volume = 1.0f; } if (volume < 0.0f) { volume = 0.0f; } this.volume = volume; } /** * Sets us in pause mode * * @param state true if we are paused */ private void setPaused(boolean state) { paused = state; } /** * Returns true if we are in pause mode * * @return true if paused */ private boolean isPaused() { return paused; } /** * Sets the volume on the given clip * * @param line the line to set the volume on * @param vol the volume (range 0 to 1) */ private void setVolume(SourceDataLine line, float vol) { if (line != null && line.isControlSupported (FloatControl.Type.MASTER_GAIN)) { FloatControl volumeControl = (FloatControl) line.getControl (FloatControl.Type.MASTER_GAIN); float range = volumeControl.getMaximum() - volumeControl.getMinimum(); volumeControl.setValue(vol * range + volumeControl.getMinimum()); } } /** * Starts the output of a set of data. * For this JavaStreamingAudioPlayer, it actually opens the audio line. * Since this is a streaming audio player, the <code>size</code> * parameter has no meaning and effect at all, so any value can be used. * Audio data for a single utterance should be grouped * between begin/end pairs. * * @param size supposedly the size of data between now and the end, * but since this is a streaming audio player, this parameter * has no meaning and effect at all */ public void begin(int size) { debugPrint("opening Stream..."); openLine(currentFormat); reset(); debugPrint("...Stream opened"); } /** * Marks the end of a set of data. Audio data for a single * utterance should be groupd between begin/end pairs. * * @return true if the audio was output properly, false if the * output was cancelled or interrupted. * */ public synchronized boolean end() { if (line != null) { drain(); synchronized (lineLock) { line.close(); line = null; } notify(); debugPrint("ended stream..."); } return true; } /** * Waits for all queued audio to be played * * @return true if the audio played to completion, false if * the audio was stopped * * [[[ WORKAROUND TODO * The javax.sound.sampled drain is almost working properly. On * linux, there is still a little bit of sound that needs to go * out, even after drain is called. Thus, the drainDelay. We * wait for a few hundred milliseconds while the data is really * drained out of the system * ]]] */ public boolean drain() { if (line != null) { debugPrint("started draining..."); if (line.isOpen()) { line.drain(); if (drainDelay > 0L) { try { Thread.sleep(drainDelay); } catch (InterruptedException ie) { } } } debugPrint("...finished draining"); } timer.stop("audioOut"); return !isCancelled(); } /** * Gets the amount of played since the last mark * * @return the amount of audio in milliseconds */ public synchronized long getTime() { return (line.getMicrosecondPosition() - timeOffset) / 1000L; } /** * Resets the audio clock */ public synchronized void resetTime() { timeOffset = line.getMicrosecondPosition(); } /** * Writes the given bytes to the audio stream * * @param audioData audio data to write to the device * * @return <code>true</code> of the write completed successfully, * <code> false </code>if the write was cancelled. */ public boolean write(byte[] audioData) { return write(audioData, 0, audioData.length); } /** * Writes the given bytes to the audio stream * * @param bytes audio data to write to the device * @param offset the offset into the buffer * @param size the size into the buffer * * @return <code>true</code> of the write completed successfully, * <code> false </code>if the write was cancelled. */ public boolean write(byte[] bytes, int offset, int size) { if (line == null) { return false; } int bytesRemaining = size; int curIndex = offset; if (firstSample) { firstSample = false; timer.stop("firstAudio"); } debugPrint(" au write " + bytesRemaining + " pos " + line.getMicrosecondPosition() + " avail " + line.available() + " bsz " + line.getBufferSize()); while (bytesRemaining > 0 && !isCancelled()) { if (!waitResume()) { return false; } debugPrint(" queueing cur " + curIndex + " br " + bytesRemaining); int bytesWritten; synchronized (lineLock) { bytesWritten = line.write (bytes, curIndex, Math.min(BYTES_PER_WRITE, bytesRemaining)); if (bytesWritten != bytesWritten) { debugPrint ("RETRY! bw" +bytesWritten + " br " + bytesRemaining); } // System.out.println("BytesWritten: " + bytesWritten); curIndex += bytesWritten; bytesRemaining -= bytesWritten; } debugPrint(" wrote " + " cur " + curIndex + " br " + bytesRemaining + " bw " + bytesWritten); } return !isCancelled() && !isDone(); } /** * Waits for resume. If this audio player * is paused waits for the player to be resumed. * Returns if resumed, cancelled or shutdown. * * @return true if the output has been resumed, false if the * output has been cancelled or shutdown. */ private synchronized boolean waitResume() { while (isPaused() && !isCancelled() && !isDone()) { try { debugPrint(" paused waiting "); wait(); } catch (InterruptedException ie) { } } return !isCancelled() && !isDone(); } /** * Returns the name of this audioplayer * * @return the name of the audio player */ public String toString() { return "JavaStreamingAudioPlayer"; } /** * Outputs a debug message if debugging is turned on * * @param msg the message to output */ private void debugPrint(String msg) { if (debug) { System.out.println(toString() + ": " + msg); } } /** * Shows metrics for this audio player */ public void showMetrics() { timer.show("JavaStreamingAudioPlayer"); } /** * Determines if the output has been cancelled. Access to the * cancelled variable should be within a synchronized block such * as this to ensure that access is coherent. * * @return true if output has been cancelled */ private synchronized boolean isCancelled() { return cancelled; } /** * Determines if the output is done. Access to the * done variable should be within a synchronized block such * as this to ensure that access is coherent. * * @return true if output has completed */ private synchronized boolean isDone() { return done; } /** * Provides a LineListener for this clas. */ private class JavaStreamLineListener implements LineListener { /** * Implements update() method of LineListener interface. Responds * to the line events as appropriate. * * @param event the LineEvent to handle */ public void update(LineEvent event) { if (event.getType().equals(LineEvent.Type.OPEN)) { synchronized (openLock) { openLock.notifyAll(); } } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -