各位看官可以关注博主个人博客,了解更多信息。

作者:Surpasser

链接地址:https://surpass.org.cn

前言

博主的毕设系统在做一个餐厅的点餐管理系统,在记性移动端页面开发的时候突发奇想做一个呼叫服务员,扬声器发声的一个功能类似于:“工作人员请注意,桌号8001顾客正在寻求帮助!”。

实现方式

接下来就对这个小功能进行分析和实现。先写一个Demo。

  1. 首先,我们需要一个dll作为辅助。这里解释一下dll的含义(DLL(Dynamic Link Library)文件为动态链接库文件,又称“应用百程序拓展”,是软件文件类型。在Windows中,许多应用程序并不是一个度完整的可执行文件,它们被分割成一些相知对独立的动态链接库,即DLL文件,放置于道系统中。当我们执行某一个程序时,相应的版DLL文件就会被调用。一个应用程序可使用权多个DLL文件,一个DLL文件也可能被不同的应用程序使用,这样的DLL文件被称为共享DLL文件)。

    需要把jacob-1.17-M2-x64.dll复制到C:\Windows\System32\目录下。我们也能看到目录下有很多的.dll文件。

    这里的文件大家自己百度下,很好找的。

  2. 使用maven项目导入坐标。

    <!-- https://mvnrepository.com/artifact/net.sf.jacob-project/jacob -->
    <dependency>
    <groupId>net.sf.jacob-project</groupId>
    <artifactId>jacob</artifactId>
    <version>1.14.3</version>
    </dependency>
  3. 测试类代码。

    /**
    * 文字转语音测试 jdk bin文件中需要导入jacob-1.17-M2-x64.dll
    * 注意导包哈
    * @date: 2020年2月25日 上午10:05:21
    */
    public class Jacobtest { public static void main(String[] args) {
    textToSpeech("工作人员请注意,桌号8001顾客正在寻求帮助!!");
    } /**
    * 语音转文字并播放
    *
    * @param text
    */
    public static void textToSpeech(String text) {
    ActiveXComponent ax = null;
    try {
    ax = new ActiveXComponent("Sapi.SpVoice"); // 运行时输出语音内容
    Dispatch spVoice = ax.getObject();
    // 音量 0-100
    ax.setProperty("Volume", new Variant(100));
    // 语音朗读速度 -10 到 +10
    ax.setProperty("Rate", new Variant(0));
    // 执行朗读
    Dispatch.call(spVoice, "Speak", new Variant(text)); /* // 下面是构建文件流把生成语音文件 ax = new ActiveXComponent("Sapi.SpFileStream");
    Dispatch spFileStream = ax.getObject(); ax = new ActiveXComponent("Sapi.SpAudioFormat");
    Dispatch spAudioFormat = ax.getObject(); // 设置音频流格式
    Dispatch.put(spAudioFormat, "Type", new Variant(22));
    // 设置文件输出流格式
    Dispatch.putRef(spFileStream, "Format", spAudioFormat);
    // 调用输出 文件流打开方法,创建一个.wav文件
    Dispatch.call(spFileStream, "Open", new Variant("./text.wav"), new Variant(3), new Variant(true));
    // 设置声音对象的音频输出流为输出文件对象
    Dispatch.putRef(spVoice, "AudioOutputStream", spFileStream);
    // 设置音量 0到100
    Dispatch.put(spVoice, "Volume", new Variant(100));
    // 设置朗读速度
    Dispatch.put(spVoice, "Rate", new Variant(-2));
    // 开始朗读
    Dispatch.call(spVoice, "Speak", new Variant(text)); // 关闭输出文件
    Dispatch.call(spFileStream, "Close");
    Dispatch.putRef(spVoice, "AudioOutputStream", null); spAudioFormat.safeRelease();
    spFileStream.safeRelease();*/
    spVoice.safeRelease();
    ax.safeRelease(); } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
  4. 从测试类可以看出,这个方法既可以发声还能输出后缀为.wav的文件,这是一个标准的多媒体文件。上述代码注释很清晰,就不解释了,自己看哈。

  5. 测试成功,现在集成到自己的项目中。

另述

这里说到了调用扬声器发声,不放还可以想一下如何调用麦克风收音。

public class EngineeCore {
String filePath = "E:\\voice\\voice_cache.wav";
AudioFormat audioFormat;
TargetDataLine targetDataLine;
boolean flag = true; private void stopRecognize() {
flag = false;
targetDataLine.stop();
targetDataLine.close();
}
private AudioFormat getAudioFormat() {
float sampleRate = 16000;
// 8000,11025,16000,22050,44100
int sampleSizeInBits = 16;
// 8,16
int channels = 1;
// 1,2
boolean signed = true;
// true,false
boolean bigEndian = false;
// true,false
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}// end getAudioFormat private void startRecognize() {
try {
// 获得指定的音频格式
audioFormat = getAudioFormat();
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
// Create a thread to capture the microphone
// data into an audio file and start the
// thread running. It will run until the
// Stop button is clicked. This method
// will return after starting the thread.
flag = true;
new CaptureThread().start();
} catch (Exception e) {
e.printStackTrace();
} // end catch
}// end captureAudio method class CaptureThread extends Thread {
public void run() {
AudioFileFormat.Type fileType = null;
File audioFile = new File(filePath); fileType = AudioFileFormat.Type.WAVE;
//声音录入的权值
int weight = 2;
//判断是否停止的计数
int downSum = 0; ByteArrayInputStream bais = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
AudioInputStream ais = null;
try {
targetDataLine.open(audioFormat);
targetDataLine.start();
byte[] fragment = new byte[1024]; ais = new AudioInputStream(targetDataLine);
while (flag) { targetDataLine.read(fragment, 0, fragment.length);
//当数组末位大于weight时开始存储字节(有声音传入),一旦开始不再需要判断末位
if (Math.abs(fragment[fragment.length-1]) > weight || baos.size() > 0) {
baos.write(fragment);
System.out.println("守卫:"+fragment[0]+",末尾:"+fragment[fragment.length-1]+",lenght"+fragment.length);
//判断语音是否停止
if(Math.abs(fragment[fragment.length-1])<=weight){
downSum++;
}else{
System.out.println("重置奇数");
downSum=0;
}
               //计数超过20说明此段时间没有声音传入(值也可更改)
if(downSum>20){
System.out.println("停止录入");
break;
} }
} //取得录音输入流
audioFormat = getAudioFormat();
byte audioData[] = baos.toByteArray();
bais = new ByteArrayInputStream(audioData);
ais = new AudioInputStream(bais, audioFormat, audioData.length / audioFormat.getFrameSize());
//定义最终保存的文件名
System.out.println("开始生成语音文件");
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, audioFile);
downSum = 0;
stopRecognize(); } catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流 try {
ais.close();
bais.close();
baos.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
}// end run
}// end inner class CaptureThread

这个测试没测试,偷个懒找的“哈哈”。

还有一点是Java操作语音文件.wav先不要研究了 :laugh and cry:,这里涉及到了语音识别,但是有百度那么些api,有兴趣的试试吧!

好了,在这里就结束了

更新

博主把自己的毕设项目打包放到自己的服务器上,这个扬声器出现了新的问题。

本来所有的基础都是在本地运行的,通过调用本地dll文件实现扬声器发声,现在部署到centOS上将会失去这个dll的支持,目前所存在的问题是如何不使用dll文件实现这个功能,中间借助了.wav后缀的音视频文件。

  • 如何在Linux上生成.wav的文件。
  • 如何获取这个文件并输出。(解释一下,用餐顾客点击手机网页的菜单,然后再餐厅的主机来播放这个声音)
  • 如何在输出主机不进行任何操作就能播放这个声音或者能够恢复之前的工作状态。

现在的临时解决办法是本地跑一个呼叫服务的接口,当需要这个功能的时候远程服务器调用本地跑的接口,进而实现餐厅主机发声。

这个和上面描述的并无差别,不一样的是存在了两台主机的调用(当然两台主机都应该链接网络,能够互相通信)

先写到这了,当有解决办法的时候再更新吧!

java如何调用本地扬声器的更多相关文章

  1. java中调用本地动态链接库(*.DLL)的两种方式详解和not found library、打包成jar,war包dll无法加载等等问题解决办法

    我们经常会遇到需要java调用c++的案例,这里就java调用DLL本地动态链接库两种方式,和加载过程中遇到的问题进行详细介绍 1.通过System.loadLibrary("dll名称,不 ...

  2. Windows下Java如何调用本地获取mac地址

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ...

  3. JAVA方法和本地方法(转载)

    转载自:http://blog.sina.com.cn/s/blog_5b9b4abe01016zw0.html JAVA中有两种方法:JAVA方法和本地方法   JAVA方法是由JAVA编写的,编译 ...

  4. JNI编程(二) —— 让C++和Java相互调用(1)

    自己在外面偷偷的算了下,又有将近两个月没更新过blog了.趁着今天有兴致,来更新JNI编程的第二篇文章.在第一篇里,大概介绍了JNI的特点.用途和优劣.并且做一个最简单的JNI的例子,不过说实话那个例 ...

  5. java方法和本地方法

    java中的方法有两种,java方法和本地方法. java方法:是由java语言编写,编译成字节码,存储在class文件中的.java方法是与平台无关的. 本地方法:本地方法是由其他语言(如C.C++ ...

  6. java jni 调用c语言函数

    今日在hibernate源代码中遇到了native关键词,甚是陌生,就查了点资料,对native是什么东西有了那么一点了解,并做一小记. native关键字说明其修饰的方法是一个原生态方法,方法对应的 ...

  7. java调用本地方法的时候报错 could not find the main class:xx.program will exit

    如图所示,当在java调用本地方法的时候报错 我的解决办法是把dll文件放到System.out.println(System.getProperty("java.library.path& ...

  8. Android使用JNI(从java调用本地函数)

    当编写一个混合有本地C代码和Java的应用程序时,需要使用Java本地接口(JNI)作为连接桥梁.JNI作为一个软件层和API,允许使用本地代码调用Java对象的方法,同时也允许在Java方法中调用本 ...

  9. [转载]java调用本地dos命令

    在社区看到java调用本地dos命令的代码,特贴出来 String command = "ipconfig"; Runtime run = Runtime.getRuntime() ...

随机推荐

  1. 混合编程:如何用python11调用C++

    摘要:在实际开发过程中,免不了涉及到混合编程,比如,对于python这种脚本语言,性能还是有限的,在一些对性能要求高的情景下面,还是需要使用c/c++来完成. 那怎样做呢?我们能使用pybind11作 ...

  2. 【java框架】SpringBoot(5)--SpringBoot整合分布式Dubbo+Zookeeper

    1.理论概述 1.1.分布式 分布式系统是若干独立计算机的集合,这些计算机对于用户来讲就像单个系统. 由多个系统集成成一个整体,提供多个功能,组合成一个板块,用户在使用上看起来是一个服务.(比如淘宝网 ...

  3. pycharm在debug时总是报UnicodeDecodeError

    1,原文链接 解决pycharm run 正常 debug 报 UnicodeDecodeError 错误的问题 2,解决方法 首先尝试 如果上面还不行

  4. 详解CURL状态码,最全的代码列表

    curl是一个强大的命令,其中我们经常使用的通过curl 加地址和端口号,判断目标链接状态,下面列出了curl 返回的状态码. 举例: [root@k8s-master1 ~]# curl k8s-m ...

  5. Java字节流和字符流,是时候总结一下IO流了

    目录 从接收输入值说起 字节流读取 字符流读取 Scanner 读取 什么是 IO 流 字节流和字符流 字节流 字节输入流 字节输出流 缓冲流的原理 字符流 字符输入流 字符输出流 为什么字符流需要 ...

  6. 【PHP】用了这么久的Laravel框架,你分析过核心架构了没

    Laravel最初的设计是为了面向MVC架构的,它可以满足如事件处理.用户身份验证等各种需求.另外它还有一个由管理数据库强力支持,用于管理模块化和可扩展性代码的软件包管理器. Laravel以其简洁. ...

  7. OO_Unit2 关于性能优化与测试的那些事

    OO_Unit2 关于性能优化与测试的那些事 OO的第2单元到本周也就正式完结了.尽管这个单元的主旋律是多线程,但"面向对象"的基本思想仍然是我们一切架构与优化的出发点与前提.因此 ...

  8. 痞子衡嵌入式:在i.MXRT启动头FDCB里调整Flash工作频率也需同步设Dummy Cycle

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是Flash工作频率与Dummy Cycle的联系. 上一篇文章 <从头开始认识i.MXRT启动头FDCB里的lookupTable ...

  9. 在Android、iOS、Web多平台使用AppGallery Connect性能管理服务

    性能管理(App Performance Management,简称APM)是华为应用市场AppGallery Connect(简称AGC)质量系列服务中的其中一项,可以提供分钟级应用性能监控能力,支 ...

  10. Neo4j/cypher学习笔记与学习建议

    简介 本笔记的主要内容是 cypher 查询语言的编写与使用. 笔记主要整理自w3cschool上的neo4j教程以及Neo4j中文网所提供的cypher中文文档,此外还包括少量从其他个人博客与官方手 ...