基于Java的简单语音朗读系统

开发环境:Eclipse软件

参考文章:http://t.csdnimg.cn/p1g0gjava文字转语音播报功能的实现方法 - 幕码人 - 博客园 (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是个性课,连选修课都不是,这怎么能行,这样一来谁会选呢,反正我没选,所以我也没学,不过我感觉所有代码都一个样。 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值