在这一篇里记录下在Java sip softphone的基础上添加播放音乐文件的功能。前面介绍了几款sipphone,发现Java sip softphone这款开源软件功能简单易于修改,根据自己的需要选择是否保留其GUI,然后修改少部分代码即可实现在拨号后播放指定的音乐文件。但是仍然有几个问题有待以后解决:1是对整个源码的框架流程的分析,目前我也只是删除了其GUI部分,而底层的sip rtp传输没有涉及;2是我下载的版本在挂断、远端忙等情况时有问题;3是播放声音文件目前只是使用默认支持的wav格式,其它格式可以扩展,但是我实现的方式应该还是有问题,因为获取发送声音数据的间隔还没有确定,只是自己测试的20ms,后面会看到。
要播放声音文件,首先得找到是从哪里获得数据的。在源码书中看到net.sourceforge.peers.media包,类Capture中看到buffer = soundManager.readData();,进而查看类SoundManager,可以发现:openAndStartLines()、 readData() 、writeData()等函数,正是我们需要的麦克风音频数据的捕获和写入扬声器的方法。查看readData()方法如下:
/**
* audio read from microphone, read all available data
* @return
*/
public synchronized byte[] readData() {
if (targetDataLine == null) {
return null;
}
int ready = targetDataLine.available();
while (ready == 0) {
try {
Thread.sleep(2);
ready = targetDataLine.available();
} catch (InterruptedException e) {
return null;
}
}
if (ready <= 0) {
return null;
}
byte[] buffer = new byte[ready];
targetDataLine.read(buffer, 0, buffer.length);
if (mediaDebug) {
try {
microphoneOutput.write(buffer, 0, buffer.length);
} catch (IOException e) {
logger.error("cannot write to file", e);
return null;
}
}
return buffer;
}
去掉调试信息,结合类Capture中的代码,发现这里仅是通过buffer将数据获取,然后通过PipedOutputStream类型的rawData将数据发送出去;因此只要在readData()中使buffer返回需要发送的声音文件数据即可。
根据以上分析,剩下的就是读取声音文件;java默认支持AU、AIFF、WAVE、MIDI 四种声音格式,如果需要更多的格式,需要下载附加包(参考1),然后先从(参考2)常用的JavaSound类图如下:

理解下从AudioSystem中获得系统的符合DataLine.info中指定的AudioFormat属性的混频器;从类SoundManager的构造函数和openAndStartLines()函数中看到如下代码:
// linear PCM 8kHz, 16 bits signed, mono-channel, little endian
audioFormat = new AudioFormat(8000, 16, 1, true, false);
targetInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
sourceInfo = new DataLine.Info(SourceDataLine.class, audioFormat);
public void openAndStartLines() {
logger.debug("openAndStartLines");
//我删除了调试部分代码
try {
targetDataLine = (TargetDataLine) AudioSystem.getLine(targetInfo);
targetDataLine.open(audioFormat);
} catch (LineUnavailableException e) {
logger.error("target line unavailable", e);
return;
}
targetDataLine.start();
try {
sourceDataLine = (SourceDataLine) AudioSystem.getLine(sourceInfo);
sourceDataLine.open(audioFormat);
} catch (LineUnavailableException e) {
logger.error("source line unavailable", e);
return;
}
sourceDataLine.start();
}
虽然看了这么多,但是我们并不需要将数据写入扬声器,只是获得并返回,因此(参考1)我们从文件中获得输入流,代码如下:
if (testNum < 1) {
File file = new File("test.wav");
// AudioInputStream audioInputStream = null;// 文件流
// AudioFormat audioFormat = null;// 文件格式
// 取得文件输入流
try {
audioInputStream = AudioSystem.getAudioInputStream(file);
} catch (UnsupportedAudioFileException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
audioFormat = audioInputStream.getFormat();
// 这里可以加入转换文件编码的代码
testNum++;
System.out.println("testNum" + testNum);
}
testNum++;
System.out.println("testNum" + testNum);
int ready = 0;
try {
ready = audioInputStream.available();
// while (ready == 0) {
try {
Thread.sleep(20);
ready = audioInputStream.available();
} catch (InterruptedException e) {
return null;
}
// }
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (ready <= 0) {
return null;
}
byte[] buffer = new byte[320];//readData是循环读取
try {
audioInputStream.read(buffer, 0, buffer.length);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("ready:" + ready);
return buffer;
然后,按照原定的采样频率、通道数等利用格式转换器将一个MP3或其它格式文件先转换成一个wav文件,就可以进行测试;特别是注意中间sleep的间隔,如果没有的话会导致数据无法及时处理而造成停顿,而且问题也在这里,这个间隔时间为多少合适,buffer读取的数据定多少呢?这个应该可以根据文件的属性来设置,但是应该有更好的方法吧?继续寻找。
最后,才想起来没有把环境的搭建过程说下,下次整理吧。
转载注明出处:http://blog.csdn.net/w7849516230/article/details/7695912
参考
1.使用Java实现MP3音乐播放器
2.javaSE播放声音原理
分享到:
相关推荐
从【压缩包子文件的文件名称列表】中的"SipPhone.msi"我们可以推断,这是一个Windows Installer包,用于在Windows操作系统上安装SIPPhone软电话客户端。MSI文件包含了安装程序的所有必要组件和设置,用户只需运行这...
7. **sounds**:此文件夹可能包含了一些声音文件,如拨号音、振铃声、忙音等,这些声音是通话过程中常见的反馈元素,增强了用户体验的真实感。 8. **呼叫中心应用**:利用这样的网页SIP客户端,可以构建一个基于Web...
- **功能**: 根据`voicemail.conf`文件中的设置来鉴别用户。 - **应用场景**: 在语音邮箱系统中对用户进行身份验证。 - **Curl** - **功能**: 接受外部URLs的数据修复。支持POST请求。 - **应用场景**: 当需要...
MagicsPhone.zip是一个包含了一系列动态链接库(DLL)文件和主执行程序的压缩包,主要用于实现SIP(Session Initiation Protocol)协议的VoIP(Voice over Internet Protocol)电话功能。在呼叫中心、客服系统以及...
在`phone.cpp`这个文件中,我们可以预见到源代码将实现上述功能的大部分或全部。C++是常用的编程语言,适用于开发这样的桌面应用程序。开发者可能会使用面向对象的设计原则,创建类来表示电话、通讯录、通话等概念,...
5. **林phone SDK**:Linphone提供SDK供开发者使用,包括必要的库文件、头文件和示例代码,以便于在不同平台上快速构建自己的VoIP应用。 6. **多媒体处理**:Linphone处理音频和视频流,使用编解码器进行数据压缩...
本压缩包中的"phone"文件可能包含了实现VoIP电话通讯技术的关键代码和文档,这些资料可以帮助你快速理解并掌握VoIP的核心概念和编程技巧。下面,我们将详细探讨网络电话涉及的一些关键知识点: 1. **编码与解码**:...
另一个文件"IPphone"很可能就是用Delphi编写的IP电话程序的可执行文件,用户可以通过运行这个文件来使用IP电话服务。 关于IP电话的知识点包括: 1. **VoIP工作原理**:VoIP将语音转换为数字信号,然后通过Internet...
这款软件是Sipphone公司开发的,它提供了基本到中级的VoIP功能,是初学者体验VoIP服务的理想选择。 汉化版意味着该软件已经过中文本地化处理,使得中国用户在使用时可以更加方便地理解和操作界面,无需面对语言障碍...
在本项目中,我们关注的是如何利用VC++(Visual C++)编程环境来实现这一功能,特别是通过调用phone.dll动态链接库来处理语音传输。以下是关于这个主题的详细知识点: 1. **VoIP基础**: - VoIP技术允许用户通过...
开发者可能在.m文件中定义了类和方法,用于处理SIP协议的逻辑,.h文件则包含了类的接口,让其他部分的代码可以调用这些方法。资源文件可能包括用户界面的设计,例如通话按钮的图标,而配置文件可能包含了服务器地址...
G.729是一种高效的声音压缩算法,主要用于实现低带宽下的高质量语音传输,尤其适用于移动网络环境。本文将详细介绍如何在iPhone应用开发中集成PJSIP库并编译支持G.729编码。 首先,PJSIP是一个开源的多媒体通信库,...