开发环境:Eclipse软件
参考文章:http://t.csdnimg.cn/p1g0g;java文字转语音播报功能的实现方法 - 幕码人 - 博客园 (cnblogs.com)
演示效果:【java自制简单语音朗读系统演示讲解】 https://www.bilibili.com/video/BV1v142117vk/?share_source=copy_web&vd_source=feda4a3e701cae91ddc70f622b5b48d6
前期准备
在Eclipse里面新建Java项目
新建java项目“yuyinhecheng”
右键“src”新建类“TextToSpeechGUI”
注意勾选“public······”
下载jacob
根据分享下载jacob,为了防止原帖主的分享过期,我这里也贴出来一下:
链接:https://pan.baidu.com/s/1xnYLVqaGWuhRTRCBEMTbnQ?pwd=1cc5 提取码: 1cc5
下载后记住自己解压的地址,原帖主说要放在C盘下面,注意!!!!一定要把那三个文件放在C盘windows的system32文件夹下面!!!要按原贴来,不然会报错!等会儿讲解怎么配置,我放在了E盘
有效文件就是jar包和两个.dll文件
配置jacob
每个版本的eclipse可能有些许出入,可以搜搜怎么搞。
首先在项目下新建一个文件夹叫“lib”
新建成功后lib里面是空的,我这里已经放东西进去了,所以不为空。把下载的jar和.dll三个文件复制放入lib内。
右键项目,点击“属性”,点击“java 构建路径”
点击添加“jar”,打开项目lib文件夹,把刚刚复制进去的jar包选中,添加并关闭(我这里已经添加了,索引lib文件夹里面没有jar包了),关闭后回到项目会发现项目中出现了“引用的库”
成功状态如下,lib中只剩.dll文件,引用库出现jar包。
现在可以开始编写项目了
开始编写
编写界面代码
问文心一言,提出自己的要求,记得要精准,例如你可以问他:帮我在eclipse用java写一个界面,上方有一个文本输入框,下方有一个按钮叫“开始朗读”,点击即可获取文本框中的文字开始朗读。
因为我们的代码中还有语速和音量这两个参数,也可以在要求中提及帮我写一个能够调节语速和音量的滑块,在文本框和按钮之间放置,接着自己微调就好了。
/*因为是实验作业,暂时还没截止,我打个标志:此代码来自武汉理工大学信息工程学院的Tiare!*/
public TextToSpeechGUI() {
setTitle("Tiare的语音朗读测试页面");
// 创建输入文本
textField = new JTextField(20);
// 创建音量滑块
volumeSlider = new JSlider(JSlider.HORIZONTAL, 0, 100, 50); // 假设100是最大音量,50是初始值
// 创建语速滑块
rateSlider = new JSlider(JSlider.HORIZONTAL, -10, 10, 0); // 假设-10到10是语速调整范围
// 创建按钮
speakButton = new JButton("开始朗读");
speakButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String textToSpeak = textField.getText();
int volume = volumeSlider.getValue(); // 假设滑块的值范围是0到100
int rateSliderValue = rateSlider.getValue(); // 假设滑块的值范围可能是任意的
try {
speakText(textToSpeak,volume,rateSliderValue);
} catch (Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(null, "Error speaking text: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
//创建保存按钮
saveAsWavButton = new JButton("保存为WAV");
saveAsWavButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String text=textField.getText();
ActiveXComponent sap = new ActiveXComponent("Sapi.SpVoice");
Dispatch sapo = sap.getObject();
saveTextAsWav(text,sapo,sap); // 假设这个方法存在并实现了保存功能
}
});
// 创建主面板并使用BorderLayout
JPanel panel = new JPanel(new BorderLayout(10, 10)); // 增加水平和垂直间距
// 添加文本字段和按钮到主面板
panel.add(textField, BorderLayout.CENTER);
panel.add(speakButton, BorderLayout.PAGE_END);
// 创建控制面板并使用FlowLayout
JPanel controlsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5)); // 增加水平和垂直间距
controlsPanel.setBorder(BorderFactory.createTitledBorder("控制")); // 添加边框和标题
// 添加标签和滑块到控制面板
controlsPanel.add(new JLabel("音量:"));
controlsPanel.add(volumeSlider);
controlsPanel.add(Box.createHorizontalStrut(10)); // 添加水平间距
controlsPanel.add(new JLabel("语速:"));
controlsPanel.add(rateSlider);
// 将控制面板添加到主面板的PAGE_END位置(即底部)
panel.add(controlsPanel, BorderLayout.PAGE_END);
// 创建一个新的面板来容纳两个按钮,这里我们使用FlowLayout来让按钮水平排列
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5)); // 5是水平和垂直间距
buttonPanel.add(speakButton); // 先添加“开始朗读”按钮
buttonPanel.add(saveAsWavButton); // 然后添加“保存”按钮
// 由于我们希望按钮在控制面板下方,我们可以使用另一个BorderLayout的面板来放置它们
JPanel bottomPanel = new JPanel(new BorderLayout());
bottomPanel.add(controlsPanel, BorderLayout.NORTH); // 控制面板在上
bottomPanel.add(buttonPanel, BorderLayout.SOUTH); // 按钮在下
panel.add(bottomPanel, BorderLayout.PAGE_END); // 将包含控件和按钮的面板添加到主面板的底部
// 添加主面板到窗口
add(panel);
// 设置窗口的大小和位置
setSize(600, 400); // 设置更大的窗口大小
setLocationRelativeTo(null); // 使窗口居中显示
// 设置窗口可见
setVisible(true);
// 设置窗口关闭时的操作
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
编写朗读代码
原帖子直接把保存文件和朗读代码放在一起了,也没有界面代码,我设了个函数实现朗读代码,需要传入三个参数,这三个参数都是需要通过界面用户输入获得:
private void speakText(String text,Integer volume,Integer rateSliderValue) throws Exception {
try {
//朗读
ActiveXComponent sap = new ActiveXComponent("Sapi.SpVoice");
Dispatch sapo = sap.getObject();
// 设置音量 0到100
Dispatch.put(sapo, "Volume", new Variant(volume));
// 设置朗读速度
Dispatch.put(sapo, "Rate", new Variant(rateSliderValue));
Dispatch.call(sapo, "Speak", new Variant(text));
sapo.safeRelease();
sap.safeRelease();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
编写保存为wav文件的代码
同理,保存文件也设置了传入参数。
public void saveTextAsWav( String text,Dispatch sapo,ActiveXComponent sap) {
// 下面是构建文件流把生成语音文件
sap = new ActiveXComponent("Sapi.SpFileStream");
Dispatch spFileStream = sap.getObject();
sap = new ActiveXComponent("Sapi.SpAudioFormat");
Dispatch spAudioFormat = sap.getObject();
// 设置音频流格式
Dispatch.put(spAudioFormat, "Type", new Variant(22));
// 设置文件输出流格式
Dispatch.putRef(spFileStream, "Format", spAudioFormat);
// 调用输出 文件流打开方法,创建一个.wav文件
Dispatch.call(spFileStream, "Open", new Variant("E:\\study\\软件设计综合实验\\生成的音频\\text.wav"), new Variant(3), new Variant(true));
// 设置声音对象的音频输出流为输出文件对象
Dispatch.putRef(sapo, "AudioOutputStream", spFileStream);
// 设置音量 0到100
Dispatch.put(sapo, "Volume", new Variant(100));
// 设置朗读速度
Dispatch.put(sapo, "Rate", new Variant(-2));
// 开始朗读
Dispatch.call(sapo, "Speak", new Variant(text));
// 关闭输出文件
Dispatch.call(spFileStream, "Close");
Dispatch.putRef(sapo, "AudioOutputStream", null);
spAudioFormat.safeRelease();
spFileStream.safeRelease();
System.out.println("Saving text to WAV file!");
}
最后是我们新建类时自动生成的,里面只要运行整体的界面代码即可。
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TextToSpeechGUI();
}
});
}
运行项目效果
音量时0-100,初始为50;语速为-10-10,初始为0;输入文本“晚上好!”,点击开始朗读即可开始;点击保存在控制台会显示保存成功。
因为我没真正在eclipse里面写过java代码,除了上学期学数据库的时候写了一点对sql的操作,其他真的不懂,有问题我就问AI了,尝试自己解决吧。下面说一下我用matlab分析合成的音频,合成音频被我保存为wav格式。
Matlab分析音频
编写代码
% 读取WAV音频文件
[audioData, sampleRate] = audioread("E:\study\软件设计综合实验\生成的音频\text.wav");
% 如果音频是多通道的(例如立体声),我们只取第一通道进行分析
if size(audioData, 2) > 1
audioData = audioData(:, 1);
end
% 分析波形
figure; % 创建新图形窗口
subplot(3, 1, 1); % 创建一个3x1的子图网格,并在第一个位置绘图
plot(0:1/sampleRate:(length(audioData)-1)/sampleRate, audioData);
xlabel('Time (s)');
ylabel('Amplitude');
title('Audio Waveform');
% 分析频谱
% 对音频数据进行FFT(快速傅里叶变换)
N = length(audioData);
Y = fft(audioData);
P2 = abs(Y/N); % 双边频谱的幅度
P1 = P2(1:N/2+1); % 单边频谱
P1(2:end-1) = 2*P1(2:end-1); % 单边频谱的幅度只计算一次,除了第一个和最后一个值
f = (0:N/2)*sampleRate/N; % 频率向量
% 绘制频谱
subplot(3, 1, 2); % 在第二个位置绘图
plot(f, P1);
xlabel('Frequency (Hz)');
ylabel('|P1(f)|');
title('Audio Spectrum');
% 如果你希望频谱以分贝(dB)为单位,你可以使用以下转换
P_dB = 10*log10(P1+eps); % eps用于防止log(0)的情况
% 绘制频谱(分贝单位)
subplot(3, 1, 3); % 在第三个位置绘图
plot(f, P_dB);
xlabel('Frequency (Hz)');
ylabel('Power/Frequency (dB/Hz)');
title('Audio Spectrum (dB)');
展示效果
我输入“晚上好!”后合成的音频文件:
运行matlab代码后:
第一个图是原始波形;
在第二个子图中绘制频谱的幅度;
在第三个子图中,将频谱的幅度转换为分贝(dB)单位,并绘制结果;
到此算是结束了,非常简单,大家也可以试试,这是我的实验作业,所以代码里面有一些注释,想起来之前做的sql学生数据库管理系统,其实也可以贴出来,不过那个好垃圾,有很多bug,我当时都没学过java就让我写数据库,我怎么可能懂,包括现在我都没系统学过java,学校设置的课真奇怪,java是个性课,连选修课都不是,这怎么能行,这样一来谁会选呢,反正我没选,所以我也没学,不过我感觉所有代码都一个样。