lxw
2020-07-11 9db52f2f2dd3665fe9da1ae5657e0167c3a34d40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
package com.fgkj.actions.media;
 
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
 
/**
 * 调用MSTTS将字符串转换成语音信息
 * 调用windows speech API(SAPI)
 * @author 
 *
 */
public class MSTTSSpeech
{
    public final static String MYMEDIA_WAV = ".wav";
    
    private int volume=100;// 声音:1到100
    private int rate=0;// 频率:-10到10
    private int voice=0;// 语音库序号
    private int audio=0;// 输出设备序号
    private ActiveXComponent ax=null;
    private Dispatch spVoice=null;// 声音对象
    private Dispatch spFileStream=null;// 音频文件输出流对象,在读取或保存音频文件时使用
    private Dispatch spAudioFormat=null;// 音频格式对象
    private Dispatch spMMAudioOut=null;// 音频输出对象
    private int formatType=22;// 音频的输出格式,默认为:SAFT22kHz16BitMono
    
    public MSTTSSpeech() 
    {
        ComThread.InitSTA();
        if(ax==null)
        {
            ax=new ActiveXComponent("Sapi.SpVoice");
            spVoice=ax.getObject();
        }
    }
    /**
     * 改变语音库
     * @param voice 语音库序号
     */
    public void changeVoice(int voice)
    {
        if(this.voice != voice)
        {
            this.voice=voice;
        }
        try
        {
            Dispatch voiceItems=Dispatch.call(spVoice,"GetVoices").toDispatch();
            int count=Integer.valueOf(Dispatch.call(voiceItems,"Count").toString());
            if(count>0)
            {
                Dispatch voiceItem=Dispatch.call(voiceItems,"Item",new Variant(this.voice)).toDispatch();
                Dispatch.put(spVoice,"Voice",voiceItem);
            }
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }
    /**
     * 改变音频输出设备
     * @param audio 音频设备序号
     */
    public void changeAudioOutput(int audio)
    {
        if(this.audio != audio)
        {
            this.audio=audio;
        }
        try
        {
            Dispatch audioOutputs=Dispatch.call(spVoice,"GetAudioOutputs").toDispatch();
            int count=Integer.valueOf(Dispatch.call(audioOutputs,"Count").toString());
            if(count > 0)
            {
                Dispatch audioOutput=Dispatch.call(audioOutputs,"Item",new Variant(this.audio)).toDispatch();
                Dispatch.put(spVoice,"AudioOutput",audioOutput);
            }
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }
    /**
     * 播放语音 
     * @param text 要转换成语音的文本
     */
    public void speak(String text)
    {
        this.speak(text,0);
    }
    /**
     * 停止播放语音
     */
    public void stop()
    {
        // this.speak("", 1);
        Dispatch.call(spVoice,"Pause");
    }
    /**
     * 播放语音
     * @param text 要转换成语音的文本
     * @param type 类型0:播放,1:停止
     */
    private void speak(String text,int type)
    {
        switch(type) 
        {
            case 0:
                try
                {
                    // 调整音量和读的速度
                    Dispatch.put(spVoice,"Volume",new Variant(this.volume));// 设置音量
                    Dispatch.put(spVoice,"Rate",new Variant(this.rate));// 设置速率
                    // 设置音频格式类型
                    if(spAudioFormat==null)
                    {
                        ax=new ActiveXComponent("Sapi.SpAudioFormat");
                        spAudioFormat=ax.getObject();
                        ax=new ActiveXComponent("Sapi.SpMMAudioOut");
                        spMMAudioOut=ax.getObject();
                    }
                    Dispatch.put(spAudioFormat,"Type",new Variant(this.formatType));
                    Dispatch.putRef(spMMAudioOut,"Format",spAudioFormat);
                    Dispatch.put(spVoice,"AllowAudioOutputFormatChangesOnNextSet",new Variant(false));
                    Dispatch.putRef(spVoice,"AudioOutputStream",spMMAudioOut);
                    // 开始朗读
                    Dispatch.call(spVoice,"Speak",new Variant(text));
                }
                catch(Exception e)
                {
                    System.out.println(e.getMessage());
                    e.printStackTrace();
                }
                break;
            case 1:
                try
                {
                    Dispatch.call(spVoice,"Speak",new Variant(text),new Variant(2));
                }
                catch(Exception e)
                {
                    System.out.println(e.getMessage());
                    e.printStackTrace();
                }
                break;
            default:
                break;
        }
    }
    /**
     * 获取系统中所有的语音库名称数组 
     * @return String[]
     */
    public String[] getVoices()
    {
        String[] voices=null;
        try
        {
            Dispatch voiceItems=Dispatch.call(spVoice,"GetVoices").toDispatch();
            int count=Integer.valueOf(Dispatch.call(voiceItems,"Count").toString());
            if(count > 0)
            {
                voices=new String[count];
                for(int i=0;i<count;i++)
                {
                    Dispatch voiceItem=Dispatch.call(voiceItems,"Item",new Variant(i)).toDispatch();
                    String voice=Dispatch.call(voiceItem,"GetDescription").toString();
                    voices[i]=voice;
                }
            }
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
        return voices;
    }
    /**
     * 获取音频输出设备名称数组
     * @return String[]
     */
    public String[] getAudioOutputs()
    {
        String[] result=null;
        try
        {
            Dispatch audioOutputs=Dispatch.call(spVoice,"GetAudioOutputs").toDispatch();
            int count=Integer.valueOf(Dispatch.call(audioOutputs,"Count").toString());
            if(count > 0)
            {
                result=new String[count];
                for(int i=0;i<count;i++)
                {
                    Dispatch voiceItem=Dispatch.call(audioOutputs,"Item",new Variant(i)).toDispatch();
                    String voice=Dispatch.call(voiceItem,"GetDescription").toString();
                    result[i]=voice;
                }
            }
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
        return result;
    }
    /**
     * 将文字转换成音频信号,然后输出到.WAV文件
     * @param text 文本字符串
     * @param filePath 输出文件路径
     */
    public boolean saveToWav(String text,String filePath)
    {
        boolean flag = false;
        try {
            // 创建输出文件流对象
            ax=new ActiveXComponent("Sapi.SpFileStream");
            spFileStream=ax.getObject();
            // 创建音频流格式对象
            if(spAudioFormat==null)
            {
                ax=new ActiveXComponent("Sapi.SpAudioFormat");
                spAudioFormat=ax.getObject();
            }
            // 设置音频流格式类型
            Dispatch.put(spAudioFormat,"Type",new Variant(this.formatType));
            // 设置文件输出流的格式
            Dispatch.putRef(spFileStream,"Format",spAudioFormat);
            // 调用输出文件流对象的打开方法,创建一个.wav文件
            Dispatch.call(spFileStream,"Open",new Variant(filePath),new Variant(3),new Variant(true));
            // 设置声音对象的音频输出流为输出文件流对象
            Dispatch.putRef(spVoice,"AudioOutputStream",spFileStream);
            // 调整音量和读的速度
            Dispatch.put(spVoice,"Volume",new Variant(this.volume));// 设置音量
            Dispatch.put(spVoice,"Rate",new Variant(this.rate));// 设置速率
            // 开始朗读
            Dispatch.call(spVoice,"Speak",new Variant(text));
            // 关闭输出文件流对象,释放资源
            Dispatch.call(spFileStream,"Close");
            Dispatch.putRef(spVoice,"AudioOutputStream",null);
            
            spAudioFormat.safeRelease();
            spFileStream.safeRelease();
            spVoice.safeRelease();
            ax.safeRelease();
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }
    /**
     * @return the volume
     */
    public int getVolume()
    {
        return volume;
    }
    /**
     * @param volume
     * the volume to set
     */
    public void setVolume(int volume)
    {
        this.volume = volume;
    }
    /**
     * @return the rate
     */
    public int getRate()
    {
        return rate;
    }
    /**
     * @param rate
     * the rate to set
     */
    public void setRate(int rate)
    {
        this.rate = rate;
    }
    /**
     * @return the voice
     */
    public int getVoice()
    {
        return voice;
    }
    /**
     * @param voice
     * the voice to set
     */
    public void setVoice(int voice)
    {
        this.voice = voice;
    }
    /**
     * @return the audio
     */
    public int getAudio()
    {
        return audio;
    }
    /**
     * @param audio
     * the audio to set
     */
    public void setAudio(int audio)
    {
        this.audio=audio;
    }
    /**
     * @return the ax
     */
    public ActiveXComponent getAx()
    {
        return ax;
    }
    /**
     * @param ax
     * the ax to set
     */
    public void setAx(ActiveXComponent ax)
    {
        this.ax=ax;
    }
    /**
     * @return the formatType
     */
    public int getFormatType()
    {
        return formatType;
    }
    /**
     * 设置音频输出格式类型<br>
     * SAFTDefault = -1<br>
     * SAFTNoAssignedFormat = 0<br>
     * SAFTText = 1<br>
     * SAFTNonStandardFormat = 2<br>
     * SAFTExtendedAudioFormat = 3<br>
     * // Standard PCM wave formats<br>
     * SAFT8kHz8BitMono = 4<br>
     * SAFT8kHz8BitStereo = 5<br>
     * SAFT8kHz16BitMono = 6<br>
     * SAFT8kHz16BitStereo = 7<br>
     * SAFT11kHz8BitMono = 8<br>
     * SAFT11kHz8BitStereo = 9<br>
     * SAFT11kHz16BitMono = 10<br>
     * SAFT11kHz16BitStereo = 11<br>
     * SAFT12kHz8BitMono = 12<br>
     * SAFT12kHz8BitStereo = 13<br>
     * SAFT12kHz16BitMono = 14<br>
     * SAFT12kHz16BitStereo = 15<br>
     * SAFT16kHz8BitMono = 16<br>
     * SAFT16kHz8BitStereo = 17<br>
     * SAFT16kHz16BitMono = 18<br>
     * SAFT16kHz16BitStereo = 19<br>
     * SAFT22kHz8BitMono = 20<br>
     * SAFT22kHz8BitStereo = 21<br>
     * SAFT22kHz16BitMono = 22<br>
     * SAFT22kHz16BitStereo = 23<br>
     * SAFT24kHz8BitMono = 24<br>
     * SAFT24kHz8BitStereo = 25<br>
     * SAFT24kHz16BitMono = 26<br>
     * SAFT24kHz16BitStereo = 27<br>
     * SAFT32kHz8BitMono = 28<br>
     * SAFT32kHz8BitStereo = 29<br>
     * SAFT32kHz16BitMono = 30<br>
     * SAFT32kHz16BitStereo = 31<br>
     * SAFT44kHz8BitMono = 32<br>
     * SAFT44kHz8BitStereo = 33<br>
     * SAFT44kHz16BitMono = 34<br>
     * SAFT44kHz16BitStereo = 35<br>
     * SAFT48kHz8BitMono = 36<br>
     * SAFT48kHz8BitStereo = 37<br>
     * SAFT48kHz16BitMono = 38<br>
     * SAFT48kHz16BitStereo = 39<br>
     * <br>
     * // TrueSpeech format<br>
     * SAFTTrueSpeech_8kHz1BitMono = 40<br>
     * // A-Law formats<br>
     * SAFTCCITT_ALaw_8kHzMono = 41<br>
     * SAFTCCITT_ALaw_8kHzStereo = 42<br>
     * SAFTCCITT_ALaw_11kHzMono = 43<br>
     * SAFTCCITT_ALaw_11kHzStereo = 4<br>
     * SAFTCCITT_ALaw_22kHzMono = 44<br>
     * SAFTCCITT_ALaw_22kHzStereo = 45<br>
     * SAFTCCITT_ALaw_44kHzMono = 46<br>
     * SAFTCCITT_ALaw_44kHzStereo = 47<br>
     * <br>
     * // u-Law formats<br>
     * SAFTCCITT_uLaw_8kHzMono = 48<br>
     * SAFTCCITT_uLaw_8kHzStereo = 49<br>
     * SAFTCCITT_uLaw_11kHzMono = 50<br>
     * SAFTCCITT_uLaw_11kHzStereo = 51<br>
     * SAFTCCITT_uLaw_22kHzMono = 52<br>
     * SAFTCCITT_uLaw_22kHzStereo = 53<br>
     * SAFTCCITT_uLaw_44kHzMono = 54<br>
     * SAFTCCITT_uLaw_44kHzStereo = 55<br>
     * SAFTADPCM_8kHzMono = 56<br>
     * SAFTADPCM_8kHzStereo = 57<br>
     * SAFTADPCM_11kHzMono = 58<br>
     * SAFTADPCM_11kHzStereo = 59<br>
     * SAFTADPCM_22kHzMono = 60<br>
     * SAFTADPCM_22kHzStereo = 61<br>
     * SAFTADPCM_44kHzMono = 62<br>
     * SAFTADPCM_44kHzStereo = 63<br>
     * <br>
     * // GSM 6.10 formats<br>
     * SAFTGSM610_8kHzMono = 64<br>
     * SAFTGSM610_11kHzMono = 65<br>
     * SAFTGSM610_22kHzMono = 66<br>
     * SAFTGSM610_44kHzMono = 67<br>
     * // Other formats<br>
     * SAFTNUM_FORMATS = 68<br>
     * 
     * @param formatType
     *            音频输出格式类型
     */
    public void setFormatType(int formatType)
    {
        this.formatType=formatType;
    }
    public static void main(String[] args)
    {
        MSTTSSpeech speech=new MSTTSSpeech();
        String text="这是我的测试,物理内存至少需要512MB,建议2GB以上,虚拟内存是主机物理内存的两倍,不要设到系统盘,硬盘空闲空间大于4.77GB.";
        speech.setFormatType(6);
        // speech.setRate(-1);
        //speech.saveToWav(text,"D://111.wav");
        speech.speak(text);
    }
}