package cn.yiiguxing.plugin.translate;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import javazoom.spi.mpeg.sampled.convert.MpegFormatConversionProvider;
import javazoom.spi.mpeg.sampled.file.MpegAudioFileReader;
import org.jetbrains.annotations.NotNull;
import javax.sound.sampled.*;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
/**
* Text to speech util.
*/
public final class Speech {
private static final String TTS_URL = "http://dict.youdao.com/dictvoice?audio=%s&type=%d";
private static final Logger LOG = Logger.getInstance("#" + Speech.class.getCanonicalName());
private Speech() {
}
public enum Phonetic {
/**
* 英式发音
*/
UK(1),
/**
* 美式发音
*/
US(2);
final int value;
Phonetic(int value) {
this.value = value;
}
}
/**
* 转换为语音
*
* @param text 目标文本
* @param phonetic 音标
*/
public static void toSpeech(@NotNull final String text, @NotNull final Phonetic phonetic) {
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
play(text, phonetic);
}
});
}
private static void play(@NotNull String text, @NotNull Phonetic phonetic) {
try {
URL url = new URL(String.format(TTS_URL, text, phonetic.value));
BufferedInputStream inputStream = new BufferedInputStream(url.openStream());
AudioInputStream in = new MpegAudioFileReader().getAudioInputStream(inputStream);
AudioFormat baseFormat = in.getFormat();
AudioFormat decodedFormat = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
baseFormat.getSampleRate(),
16,
baseFormat.getChannels(),
baseFormat.getChannels() * 2,
baseFormat.getSampleRate(),
false);
AudioInputStream din = new MpegFormatConversionProvider().getAudioInputStream(decodedFormat, in);
// Play now.
rawPlay(decodedFormat, din);
in.close();
} catch (Exception e) {
LOG.error("toSpeech", e);
}
}
private static void rawPlay(AudioFormat targetFormat, AudioInputStream din)
throws IOException, LineUnavailableException {
SourceDataLine line = getLine(targetFormat);
if (line != null) {
// Start
line.start();
byte[] data = new byte[4096];
int bytesRead;
while ((bytesRead = din.read(data, 0, data.length)) != -1) {
line.write(data, 0, bytesRead);
}
// Stop
line.drain();
line.stop();
line.close();
din.close();
}
}
private static SourceDataLine getLine(AudioFormat audioFormat) throws LineUnavailableException {
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
SourceDataLine res = (SourceDataLine) AudioSystem.getLine(info);
res.open(audioFormat);
return res;
}
}