⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 703cdde2ca85001c1c07b990949a4770

📁 一个非常有意思,并且带图像的语音项目,能读出相应的英文,并有口型
💻
字号:
/**
 * Copyright 2001 Sun Microsystems, Inc.
 * 
 * See the file "license.terms" for information on usage and
 * redistribution of this file, and for a DISCLAIMER OF ALL 
 * WARRANTIES.
 */
package com.sun.speech.freetts.audio;

import javax.sound.sampled.*;

import com.sun.speech.freetts.util.BulkTimer;

/**
 * Provides an implementation of <code>AudioPlayer</code> that creates
 * javax.sound.sampled audio clips and outputs them via the
 * javax.sound API.  The interface provides a highly reliable audio
 * output package. Since audio is batched and not sent to the audio
 * layer until an entire utterance has been processed, this player has
 * higher latency (50 msecs for a typical 4 second utterance).
 *
 * The system property:
 * <code>
	com.sun.speech.freetts.audio.AudioPlayer.debug;
 * </code> if set to <code>true</code> will cause this
 * class to emit debugging information (useful to a developer).
 */
public class AnimatedAudioPlayer implements AudioPlayer {
    
    private volatile boolean paused;
    private volatile boolean done = false;
    private volatile boolean cancelled = false;
    private volatile Clip currentClip;

    private float volume = 1.0f;  // the current volume
    private boolean debug = false;
    private BulkTimer timer = new BulkTimer();
    private AudioFormat defaultFormat = // default format is 8khz
	new AudioFormat(8000f, 16, 1, true, true);
    private AudioFormat currentFormat = defaultFormat;
    private boolean firstSample = true;
    private int curIndex = 0;
    private byte[] outputData;
    private LineListener lineListener = new JavaClipLineListener();
    private long closeDelay;	// workaround for linux sound bug
	private LineListener externalLineListener; // -- added by bd
 	/**
	 * Constructs a default AnimatedAudioPlayer 
	 * -- modified by bd
	 */
	public AnimatedAudioPlayer(LineListener externalLineListener) {
		this.externalLineListener = externalLineListener;
		debug = Boolean.getBoolean
			("com.sun.speech.freetts.audio.AudioPlayer.debug");
		closeDelay = Long.getLong
			("com.sun.speech.freetts.audio.AudioPlayer.closeDelay",
				150L).longValue();
		setPaused(false);
	}
    /**
     * Sets the audio format for this player
     *
     * @param format the audio format
     *
     * @throws UnsupportedOperationException if the line cannot be opened with
     *     the given format
     */
    public synchronized void setAudioFormat(AudioFormat format) {
	currentFormat = format;
    }

    /**
     * Retrieves the audio format for this player
     *
     * @return format the audio format
     */
    public AudioFormat getAudioFormat() {
	return currentFormat;
    }



    /**
     * Pauses audio output.   All audio output is 
     * stopped. Output can be resumed at the
     * current point by calling <code>resume</code>. Output can be
     * aborted by calling <code> cancel </code>
     */
    public synchronized void pause() {
	if (!isPaused()) {
	    setPaused(true);
	    Clip clip = currentClip;
	    if (clip != null) {
	        clip.stop();
	    }
	}
    }

    /**
     * Resumes playing audio after a pause.
     *
     */
    public synchronized void resume() {
	if (isPaused()) {
	    setPaused(false);
	    Clip clip = currentClip;
	    if (clip != null) {
		clip.start();
	    }
	    notify();
	}
    }
	
    /**
     * Cancels all queued audio. Any 'write' in process will return
     * immediately false.
     */
    public synchronized void cancel() {
	cancelled = true;
	Clip clip = currentClip;
	if (clip != null) {
	    clip.close();
	}
    }

    /**
     * Prepares for another batch of output. Larger groups of output
     * (such as all output associated with a single FreeTTSSpeakable)
     * should be grouped between a reset/drain pair.
     */
    public synchronized void reset() {
	timer.start("speakableOut");
    }

    /**
     * Waits for all queued audio to be played
     *
     * @return <code>true</code> if the write completed successfully, 
     *       	<code> false </code>if the write was cancelled.
     */
    public boolean drain()  {
	timer.stop("speakableOut");
	return true;
    }

    /**
     * Closes this audio player
     */
    public synchronized void close() {
	done = true;
	notify();
    }
        

    /**
     * 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;
	Clip clip = currentClip;
	if (clip != null) {
	    setVolume(clip, volume);
	}
    }	      


    /**
     * Sets 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 <code> true </code>if paused; 
     *		otherwise returns <code>false</code>
     */
    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(Clip clip, float vol) {
	if (clip.isControlSupported (FloatControl.Type.MASTER_GAIN)) {
	    FloatControl volumeControl = 
		(FloatControl) clip.getControl (FloatControl.Type.MASTER_GAIN);
	    float range = volumeControl.getMaximum() -
			  volumeControl.getMinimum();
	    volumeControl.setValue(vol * range + volumeControl.getMinimum());
	}
    }




    /**
     * Returns the current position in the output stream since the
     * last <code>resetTime</code> 
     *
     * Currently not supported.
     *
     * @return the position in the audio stream in milliseconds
     *
     */
    public synchronized long getTime()  {
        return -1L;
    }


    /**
     * Resets the time for this audio stream to zero
     */
    public synchronized void resetTime() {
    }
    

    /**
     *  Starts the output of a set of data. Audio data for a single
     *  utterance should be grouped between begin/end pairs.
     *
     * @param size the size of data between now and the end
     *
     */
    public void begin(int size) {
	cancelled = false;
	timer.start("utteranceOutput");
	curIndex = 0;
	outputData = new byte[size];
    }

    /**
     *  Marks the end a set of data. Audio data for a single utterance should
     *  be grouped between begin/end pairs.
     *
     *  @return <code>true</code> if the audio was output properly, 
     * 		<code>false </code> if the output was cancelled 
     *		or interrupted.
     */
    public synchronized boolean  end()  {
	boolean ok = true;

	while (!done && !cancelled && isPaused()) {
	    try { 
		wait();
	    } catch (InterruptedException ie) {
		return false;
	    }
	}

	if (done || cancelled) {
	    cancelled = false;
	    return false;
	}

	timer.start("clipGeneration");
	try {
	    DataLine.Info info = new DataLine.Info(Clip.class, currentFormat);
	    Clip clip = (Clip) AudioSystem.getLine(info);

	    clip.addLineListener(lineListener);
	    clip.addLineListener(externalLineListener); // -- added by bd
	    clip.open(currentFormat, outputData, 0, outputData.length);
	    setVolume(clip, volume);

	    if (currentClip != null) {
		throw new IllegalStateException("clip already set");
	    }
	    currentClip = clip;
	    clip.start();

	    try {
		while (currentClip != null) {
		    wait();	// drain does not work 
		}
	    } catch (InterruptedException ie) {
		ok = false;
	    }
	} catch (LineUnavailableException lue) {
	    System.err.println("Line unavailable");
	    System.err.println("Format is " + currentFormat);
	    ok = false;
	}

	timer.stop("clipGeneration");
	timer.stop("utteranceOutput");
	ok = !cancelled;
	cancelled = false;
	return ok;
    }

    
    /**
     * Writes the given bytes to the audio stream
     *
     * @param audioData audio data to write to the device
     *
     * @return <code>true</code> if 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> if the write completed successfully, 
     *       	<code> false </code>if the write was cancelled.
     */
    public boolean write(byte[] bytes, int offset, int size) {

	if (firstSample) {
	    firstSample = false;
	    timer.stop("firstAudio");
	}
	System.arraycopy(bytes, offset, outputData, curIndex, size);
	curIndex += size;
	return true;
    }


    /**
     * Returns the name of this audio player
     *
     * @return the name of the audio player
     */
    public String toString() {
	return "JavaClipAudioPlayer";
    }


    /**
     * Outputs the given msg if debugging is enabled for this
     * audio player.
     */
    private void debugPrint(String msg) {
	if (debug) {
	    System.out.println(toString() + ": " + msg);
	}
    }

    /**
     * Shows metrics for this audio player
     */
    public void showMetrics() {
	timer.show(toString());
    }

    /**
     * Starts the first sample timer
     */
    public void startFirstSampleTimer() {
	timer.start("firstAudio");
	firstSample = true;
    }


    /**
     * Provides a LineListener for this clas.
     */
    private class JavaClipLineListener 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.START)) {
		debugPrint("Event  START");
	    } else if (event.getType().equals(LineEvent.Type.STOP)) {
		debugPrint("Event  STOP");
		// A line may be stopped for three reasons:
		//    the clip has finished playing
		//    the clip has been paused
		//    the clip has been cancelled (i.e. closed)
		// if the clip has stopped because it has finished
		// playing, then we should close the clip, otherwise leave
		// it alone
		synchronized(AnimatedAudioPlayer.this) {
		    if (!cancelled && !isPaused()) {

	// BUG:
	// There is a javax.sound bug that causes a crash on linux
	// it is described here:
	// http://developer.java.sun.com/developer/bugParade/bugs/4498848.html
	// The bug seems to be related to synchronization of the close
	// call on the clip.  If we delay before the close by 
	// a small amount, the crash is averted.  This is a WORKAROUND
	// only and should be removed once the javax.sound bug is
	// fixed.  We get the delay from the property:
	//
	// com.sun.speech.freetts.audio.AudioPlayer.closeDelay
	// 
	// 
			try {
			    if (closeDelay > 0L) {
				Thread.sleep(closeDelay);
			    }
		    	} catch (InterruptedException ie) {
			}
			currentClip.close();
		    }
		}
	    }  else if (event.getType().equals(LineEvent.Type.OPEN)) {
		debugPrint("Event OPEN");
	    }  else if (event.getType().equals(LineEvent.Type.CLOSE)) {
		// When a clip is closed we no longer need it, so 
		// set currentClip to null and notify anyone who may
		// be waiting on it.
		debugPrint("EVNT CLOSE");
		synchronized (AnimatedAudioPlayer.this) {
		    currentClip = null;
		    AnimatedAudioPlayer.this.notify();
		}
	    }
	}
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -