001/**
002 * Portions Copyright 2001 Sun Microsystems, Inc.
003 * Portions Copyright 1999-2001 Language Technologies Institute, 
004 * Carnegie Mellon University.
005 * All Rights Reserved.  Use is subject to license terms.
006 * 
007 * See the file "license.terms" for information on usage and
008 * redistribution of this file, and for a DISCLAIMER OF ALL 
009 * WARRANTIES.
010 */
011package com.sun.speech.freetts.relp;
012
013import java.io.IOException;
014import java.util.logging.Level;
015import java.util.logging.Logger;
016
017import javax.sound.sampled.AudioFormat;
018
019import com.sun.speech.freetts.ProcessException;
020import com.sun.speech.freetts.Utterance;
021import com.sun.speech.freetts.UtteranceProcessor;
022import com.sun.speech.freetts.audio.AudioPlayer;
023
024/**
025 * Supports generating audio output from an utterance. This is an
026 * utterance processor. The primary method, <code> procesUtterance </code> 
027 * takes an utterance and hands it off to the LPCResult to be sent to the
028 * proper audio player.
029 *
030 * @see LPCResult
031 */
032public class AudioOutput implements UtteranceProcessor {
033    /** Logger instance. */
034    private static final Logger LOGGER =
035        Logger.getLogger(AudioOutput.class.getName());
036
037    private final static AudioFormat AUDIO_8KHZ =
038        new AudioFormat(8000.0f, 16, 1, true, true);
039    private final static AudioFormat AUDIO_16KHZ =
040        new AudioFormat(16000.0f, 16, 1, true, true);
041    
042    /**
043     * Generates audio waves for the given Utterance. The audio data
044     * is decoded using the Linear Predictive Decoder
045     *
046     * @param  utterance  the utterance to generate waves
047     *
048     * @see LPCResult
049     *
050     * @throws ProcessException if an IOException is thrown during the
051     *         processing of the utterance
052     */
053    public void processUtterance(Utterance utterance) throws ProcessException {
054        LPCResult lpcResult = (LPCResult) utterance.getObject("target_lpcres");
055        SampleInfo sampleInfo = 
056            (SampleInfo) utterance.getObject(SampleInfo.UTT_NAME);
057        AudioPlayer audioPlayer = utterance.getVoice().getAudioPlayer();
058
059        audioPlayer.setAudioFormat(getAudioFormat(sampleInfo));
060        audioPlayer.setVolume(utterance.getVoice().getVolume());
061
062        if (LOGGER.isLoggable(Level.FINE)) {
063            LOGGER.fine("=== " +
064                utterance.getString("input_text"));
065        }
066        try {
067            if (!lpcResult.playWave(audioPlayer, utterance)) {
068                throw new ProcessException("Output Cancelled");
069            }
070        } catch (IOException e) {
071            throw new ProcessException(e.getMessage(), e);
072        }
073    }
074
075
076    /**
077     * Gets the current audio format.  
078     * Given a sample info return an appropriate audio format. A cache
079     * of common audio formats is used to reduce unnecessary object
080     * creation. Note that this method always returns an AudioFormat
081     * that uses 16-bit samples.
082     *
083     * @param sampleInfo the sample info
084     *
085     * @return an audio format
086     */
087    private AudioFormat getAudioFormat(SampleInfo sampleInfo) {
088        if (sampleInfo.getSampleRate() == 8000) {
089            return AUDIO_8KHZ;
090        } else if (sampleInfo.getSampleRate() == 16000) {
091            return AUDIO_16KHZ;
092        } else {
093            return new AudioFormat(sampleInfo.getSampleRate(),
094                    16, 1, true, true);
095        }
096    }
097    
098    /**
099     * 
100     * Returns the string form of this object
101     * 
102     * @return the string form of this object
103     */
104    public String toString() {
105        return "AudioOutput";
106    }
107}
108