All Downloads are FREE. Search and download functionalities are using the official Maven repository.

marytts.client.RemoteMaryInterface Maven / Gradle / Ivy

The newest version!
package marytts.client;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

import org.w3c.dom.Document;

import marytts.MaryInterface;
import marytts.client.MaryClient.DataType;
import marytts.client.MaryClient.Voice;
import marytts.exceptions.SynthesisException;
import marytts.util.dom.DomUtils;
import marytts.util.http.Address;

public class RemoteMaryInterface implements MaryInterface {
	private MaryClient client;
	private DataType inputType;
	private DataType outputType;
	private Locale locale;
	private String voiceName;
	private String effects;
	private String style;
	private String outputTypeParams;
	private boolean isStreaming;
	private Vector availableVoices;
	private Set availableLocales;
	private Map availableDataTypes;

	public RemoteMaryInterface() throws IOException {
		client = MaryClient.getMaryClient();
		init();
	}

	public RemoteMaryInterface(String serverHost, int serverPort) throws IOException {
		client = MaryClient.getMaryClient(new Address(serverHost, serverPort));
		init();
	}

	private void init() throws IOException {
		setReasonableDefaults();
	}

	private void setReasonableDefaults() throws IOException {
		availableDataTypes = new HashMap();
		for (DataType d : client.getAllDataTypes()) {
			availableDataTypes.put(d.name(), d);
		}
		availableLocales = client.getLocales();
		availableVoices = client.getVoices();

		inputType = availableDataTypes.get("TEXT");
		outputType = availableDataTypes.get("AUDIO");
		if (availableLocales.contains(Locale.US)) {
			locale = Locale.US;
		} else {
			locale = availableLocales.iterator().next();
		}
		voiceName = getDefaultVoice(locale);
		effects = null;
		style = null;
		outputTypeParams = null;
		isStreaming = false;
	}

	@Override
	public void setInputType(String newInputType) throws IllegalArgumentException {
		DataType inType = availableDataTypes.get(newInputType);
		if (inType == null) {
			throw new IllegalArgumentException("No such data type: " + newInputType);
		} else if (!inType.isInputType()) {
			throw new IllegalArgumentException("Not an input type: " + newInputType);
		}
		inputType = inType;
	}

	@Override
	public String getInputType() {
		return inputType.name();
	}

	@Override
	public void setOutputType(String newOutputType) throws IllegalArgumentException {
		DataType outType = availableDataTypes.get(newOutputType);
		if (outType == null) {
			throw new IllegalArgumentException("No such data type: " + newOutputType);
		} else if (!outType.isOutputType()) {
			throw new IllegalArgumentException("Not an output type: " + newOutputType);
		}
		outputType = outType;
	}

	@Override
	public String getOutputType() {
		return outputType.name();
	}

	@Override
	public void setLocale(Locale newLocale) throws IllegalArgumentException {
		if (!availableLocales.contains(newLocale)) {
			throw new IllegalArgumentException("Unsupported locale: " + newLocale);
		}
		locale = newLocale;
		voiceName = getDefaultVoice(locale);
	}

	private String getDefaultVoice(Locale loc) {
		for (Voice v : availableVoices) {
			if (v.getLocale().equals(loc)) {
				return v.name();
			}
		}
		return null;
	}

	@Override
	public Locale getLocale() {
		return locale;
	}

	@Override
	public void setVoice(String newVoiceName) throws IllegalArgumentException {
		for (Voice v : availableVoices) {
			if (v.name().equals(newVoiceName)) {
				voiceName = newVoiceName;
				locale = v.getLocale();
				return;
			}
		}
		throw new IllegalArgumentException("Not a valid voice name: " + newVoiceName);
	}

	@Override
	public String getVoice() {
		return voiceName;
	}

	@Override
	public void setAudioEffects(String audioEffects) {
		effects = audioEffects;
	}

	@Override
	public String getAudioEffects() {
		return effects;
	}

	@Override
	public void setStyle(String newStyle) {
		style = newStyle;
	}

	@Override
	public String getStyle() {
		return style;
	}

	@Override
	public void setOutputTypeParams(String params) {
		outputTypeParams = params;
	}

	@Override
	public String getOutputTypeParams() {
		return outputTypeParams;
	}

	@Override
	public void setStreamingAudio(boolean newIsStreaming) {
		isStreaming = newIsStreaming;
		if (isStreaming) {
			throw new RuntimeException("Streaming audio not yet implemented in this interface");
		}
	}

	@Override
	public boolean isStreamingAudio() {
		return isStreaming;
	}

	@Override
	public String generateText(String text) throws SynthesisException {
		verifyInputTypeIsText();
		verifyOutputTypeIsText();
		try {
			byte[] result = processStringToBytes(text);
			return new String(result, "UTF-8");
		} catch (Exception ioe) {
			throw new SynthesisException(ioe);
		}
	}

	@Override
	public String generateText(Document doc) throws SynthesisException {
		verifyInputTypeIsXML();
		verifyOutputTypeIsText();
		try {
			String xmlAsString = DomUtils.document2String(doc);
			byte[] result = processStringToBytes(xmlAsString);
			return new String(result, "UTF-8");
		} catch (Exception ioe) {
			throw new SynthesisException(ioe);
		}
	}

	@Override
	public Document generateXML(String text) throws SynthesisException {
		verifyInputTypeIsText();
		verifyOutputTypeIsXML();
		try {
			byte[] result = processStringToBytes(text);
			return DomUtils.parseDocument(new ByteArrayInputStream(result));
		} catch (Exception ioe) {
			throw new SynthesisException(ioe);
		}
	}

	@Override
	public Document generateXML(Document doc) throws SynthesisException {
		verifyInputTypeIsXML();
		verifyOutputTypeIsXML();
		try {
			String xmlAsString = DomUtils.document2String(doc);
			byte[] result = processStringToBytes(xmlAsString);
			return DomUtils.parseDocument(new ByteArrayInputStream(result));
		} catch (Exception ioe) {
			throw new SynthesisException(ioe);
		}
	}

	@Override
	public AudioInputStream generateAudio(String text) throws SynthesisException {
		verifyInputTypeIsText();
		verifyOutputTypeIsAudio();
		try {
			byte[] result = processStringToBytes(text);
			return AudioSystem.getAudioInputStream(new ByteArrayInputStream(result));
		} catch (Exception ioe) {
			throw new SynthesisException(ioe);
		}
	}

	@Override
	public AudioInputStream generateAudio(Document doc) throws SynthesisException {
		verifyInputTypeIsXML();
		verifyOutputTypeIsAudio();
		try {
			String xmlAsString = DomUtils.document2String(doc);
			byte[] result = processStringToBytes(xmlAsString);
			return AudioSystem.getAudioInputStream(new ByteArrayInputStream(result));
		} catch (Exception ioe) {
			throw new SynthesisException(ioe);
		}
	}

	private byte[] processStringToBytes(String input) throws Exception {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		client.process(input, inputType.name(), outputType.name(), locale.toString(), "WAVE", voiceName, style, effects,
				outputTypeParams, baos, 0);
		return baos.toByteArray();
	}

	private static final Set KNOWN_TEXT_TYPES = new HashSet(Arrays.asList(new String[] {
			"HALFPHONE_TARGETFEATURES", "HTSCONTEXT", "MBROLA", "PRAAT_TEXTGRID", "REALISED_DURATIONS", "SIMPLEPHONEMES",
			"TARGETFEATURES", "TEXT" }));

	private static final Set KNOWN_XML_TYPES = new HashSet(Arrays.asList(new String[] { "ACOUSTPARAMS",
			"ALLOPHONES", "APML", "DURATIONS", "INTONATION", "PARTSOFSPEECH", "PHONEMES", "RAWMARYXML", "REALISED_ACOUSTPARAMS",
			"SABLE", "SSML", "TOKENS", "WORDS" }));

	private static final Set KNOWN_AUDIO_TYPES = new HashSet(Arrays.asList(new String[] { "AUDIO" }));

	private void verifyOutputTypeIsXML() {
		// Approximate verification: we catch things we know cannot be right
		if (KNOWN_TEXT_TYPES.contains(outputType.name()) || KNOWN_AUDIO_TYPES.contains(outputType.name())) {
			throw new IllegalArgumentException("Cannot provide XML output for non-XML-based output type " + outputType);
		}
	}

	private void verifyInputTypeIsXML() {
		// Approximate verification: we catch things we know cannot be right
		if (KNOWN_TEXT_TYPES.contains(inputType.name()) || KNOWN_AUDIO_TYPES.contains(inputType.name())) {
			throw new IllegalArgumentException("Cannot provide XML input for non-XML-based input type " + inputType);
		}
	}

	private void verifyInputTypeIsText() {
		// Approximate verification: we catch things we know cannot be right
		if (KNOWN_XML_TYPES.contains(inputType.name()) || KNOWN_AUDIO_TYPES.contains(inputType.name())) {
			throw new IllegalArgumentException("Cannot provide plain-text input for XML-based input type " + inputType);
		}
	}

	private void verifyOutputTypeIsAudio() {
		if (!outputType.name().equals("AUDIO")) {
			throw new IllegalArgumentException("Cannot provide audio output for non-audio output type " + outputType);
		}
	}

	private void verifyOutputTypeIsText() {
		// Approximate verification: we catch things we know cannot be right
		if (KNOWN_XML_TYPES.contains(outputType.name()) || KNOWN_AUDIO_TYPES.contains(outputType.name())) {
			throw new IllegalArgumentException("Cannot provide text output for non-text output type " + outputType);
		}
	}

	@Override
	public Set getAvailableVoices() {
		Set voices = new HashSet();
		for (Voice v : availableVoices) {
			voices.add(v.name());
		}
		return voices;
	}

	@Override
	public Set getAvailableVoices(Locale aLocale) {
		Set voices = new HashSet();
		for (Voice v : availableVoices) {
			if (v.getLocale().equals(aLocale))
				voices.add(v.name());
		}
		return voices;
	}

	@Override
	public Set getAvailableLocales() {
		return Collections.unmodifiableSet(availableLocales);
	}

	@Override
	public Set getAvailableInputTypes() {
		Set inputTypes = new HashSet();
		for (DataType d : availableDataTypes.values()) {
			if (d.isInputType()) {
				inputTypes.add(d.name());
			}
		}
		return inputTypes;
	}

	@Override
	public Set getAvailableOutputTypes() {
		Set outputTypes = new HashSet();
		for (DataType d : availableDataTypes.values()) {
			if (d.isOutputType()) {
				outputTypes.add(d.name());
			}
		}
		return outputTypes;
	}

	@Override
	public boolean isTextType(String dataType) {
		return KNOWN_TEXT_TYPES.contains(dataType);
	}

	@Override
	public boolean isXMLType(String dataType) {
		return KNOWN_XML_TYPES.contains(dataType);
	}

	@Override
	public boolean isAudioType(String dataType) {
		return KNOWN_AUDIO_TYPES.contains(dataType);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy