// 把一个ALAW/ULAW声音转换成PCM以便回放
if ((format.getEncoding() == AudioFormat.Encoding.ULAW) ||
(format.getEncoding() == AudioFormat.Encoding.ALAW))
{
AudioFormat tmpFormat = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
format.getSampleRate(), format.getSampleSizeInBits() * 2,
format.getChannels(), format.getFrameSize() * 2,
format.getFrameRate(), true);
stream = AudioSystem.getAudioInputStream(tmpFormat, stream);
format = tmpFormat;
}
DataLine.Info info = new DataLine.Info(
Clip.class, format,
((int) stream.getFrameLength() * format.getFrameSize()));
if (line==null)
{
// 输出线还没有实例化
// 是否能够找到合适的输出线类型?
DataLine.Info outInfo = new DataLine.Info(SourceDataLine.class,
format);
if (!AudioSystem.isLineSupported(outInfo))
{
System.out.println("不支持匹配" + outInfo + "的输出线");
throw new Exception("不支持匹配" + outInfo + "的输出线");
}
// 打开输出线
line = (SourceDataLine) AudioSystem.getLine(outInfo);
line.open(format, 50000);
line.start();
}
int frameSizeInBytes = format.getFrameSize();
int bufferLengthInFrames = line.getBufferSize() / 8;
int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;
byte[] data=new byte[bufferLengthInBytes];
// 读取字节数据,并计数
int numBytesRead = 0;
if ((numBytesRead = stream.read(data)) != -1)
{
int numBytesRemaining = numBytesRead;
}
// 把字节数据切割成合适的大小
byte[] newData=new byte[numBytesRead];
for (int i=0; i
newData[i]=data[i];
return newData;
}
catch (Exception e)
{
return new byte[0];
}
}
这就是全部的代码,包括注释在内,一个大约150行代码的语音合成器。
三、文本-语音转换
以语音元素的格式指定待朗读的单词似乎过于复杂,如果要构造一个能够朗读文本(比如Web页面或Email)的应用,我们希望能够直接指定原始的文本。
深入分析这个问题之后,我在本文后面的ZIP文件中提供了一个试验性的文本-语音转换类。运行这个类,它将显示出分析结果。文本-语音转换类可以从命令行执行,如下所示:
java com.lotontech.speech.Converter "hello there"
输出结果类如:
hello -> h|e|l|oo
there -> dth|aer
如果运行下面这个命令:
java com.lotontech.speech.Converter "I like to read JavaWorld"
则输出结果为:
i -> ii
like -> l|ii|k
to -> t|ouu
read -> r|ee|a|d
java -> j|a|v|a
world -> w|err|l|d
这个转换类是如何工作的呢?实际上,我的方法相当简单,转换过程就是以一定的次序应用一组文本替换规则。例如对于单词“ant”、“want”、“wanted”、“unwanted”和“unique”,则我们想要应用的替换规则可能依次为:
用“|y|ou|n|ee|k|”替换“*unique*”
用“|w|o|n|t|”替换“*want*”
用“|a|”替换“*a*”
用“|e|”替换“*e*”
用“|d|”替换“*d*”
用“|n|”替换“*n*”
(编辑:aniston)
|