Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
DIY综合交流区
[RealTouch活动]VOIP在RT-Thread上的应用
发布于 2012-09-08 11:20:49 浏览:25373
订阅该版
**报名题目** VoIP在RT-Thread上的应用 **项目背景** VoIP(Voice over Internet Protocol)简而言之就是将模拟声音讯号(Voice)数字化,以数据封包(Data Packet)的形式在 IP 数据网络 (IP Network)上做实时传递。VoIP最大的优势是能广泛地采用Internet和全球IP互连的环境,提供比传统业务更多、更好的服务。VoIP可以在IP网络上便宜的传送语音、传真、视频、和数据等业务,如统一消息、虚拟电话、虚拟语音/传真邮箱、查号业务、Internet呼叫中心、Internet呼叫管理、电视会议、电子商务、传真存储转发和各种信息的存储转发等。VoIP的基本原理是:通过语音的压缩算法对语音数据编码进行压缩处理,然后把这些语音数据按 TCP/IP 标准进行打包,经过 IP 网络把数据包送至接收地,再把这些语音数据包串起来,经过解压处理后,恢复成原来的语音信号,从而达到由互联网传送语音的目的。(来源于百度百科) 随着网络的速度越来越快,使得VoIP得到了更为广泛的应用,比如QQ。更值可喜的是移动网络的速度也得到提高,使VoIP可以在移动设备上应用,如微信。使用过微信的朋友应该都知道微信可以发送语言,并且延时不是很大(3~8s),最近微信还添加了视频功能,视频的延时也不大(3~8s)。根据我目前使用CMDA网络传输语音的经验也是3~5s(还有优化的可能)。(我自己写的,表述很有问题) **初步计划** 1.学习realtoch的语音播放与录音功能 2.移植speex语音压缩解压软件到realtouch,现实本地语音压缩与解压 3.学习realtouch的TCP/IP的使用(包括wifi) 4.制定通信协议(暂时不用标准的协议,怕涉及的东西太多) 5.搭建简单服务器(使用VC编写) 6.基本功能合成 7.学习RTGUI添加界面 8.整体合成 **最终成果** 通过realtouch加载VoIp应用程序,像使用“微信语音”发送一样把语音发送到指定的终端realtouch去,实现语音通信。 **其他** 由于我的表达能力不是很好,有什么问题请指正。同时也希望各位网友参与进来学习与指导。 注:到了测试外网通信时,希望有外网的IP地址(由于我在学校里弄不到外网IP地址)网友能提供一个给测试。 下载附件 [读写WAV音频文件.7z](https://oss-club.rt-thread.org/uploads/3847_56c45cb7431360cb32b0c8d3e682d49a.7z) 下载附件 [1~10s.7z](https://oss-club.rt-thread.org/uploads/3847_1bbe1afabfc05e8df0e428ee8d33cdbf.7z) 下载附件 [encode_decode.7z](https://oss-club.rt-thread.org/uploads/3847_0aa5367b51140e6f436c4f5bdd443c90.7z) 下载附件 [10s.7z](https://oss-club.rt-thread.org/uploads/3847_f5ea115e19d4f7a4ac264af9bc5b0a00.7z) ![ccme_ds_7941.jpg](https://oss-club.rt-thread.org/uploads/53_3901876f2d88a0f64ae9a1201dcc4609.jpg)
查看更多
50
个回答
默认排序
按发布时间排序
lindabell
2012-09-08
这家伙很懒,什么也没写!
占位,该楼用来更新进度和资料用 这个项目的代码存放在github:[https://github.com/lindabell/VoIP_RT_Thread](https://github.com/lindabell/VoIP_RT_Thread) 注:我还不是很会使用github,可能会会有问题 代码重新整理并转到[https://github.com/lindabell/VoIP_RTT](https://github.com/lindabell/VoIP_RTT) 【2013.5.13】 **进度** **1.学习realtoch的语音播放与录音功能 (2012.9.8~2012.10.20)** ①在网上找的[https://github.com/lindabell/VoIP_RT_Thread/raw/5b5b4d031574fac8b70e487a1ee1de80efd92e2f/APP/examples/5_media_mp3/Helix%20MP3%E8%A7%A3%E7%A0%81%E5%99%A8%E7%A7%BB%E6%A4%8D.pdf](Helix MP3解码器移植文档)(Add:2012.9.10) ②[https://github.com/lindabell/VoIP_RT_Thread/raw/master/APP/examples/5_media_mp3/MP3%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F%E8%A7%A3%E6%9E%90.pdf](MP3文件格式解析PDF)(Add:2012.9.12) ③基本了解heilx MP3的使用了,但还有些问题。参见x楼(Add:2012.9.14) ④播放中有“咔咔”的声音解决(详细参见本帖后面楼层(抱怨一下怎么没有楼层的?))(add:2012.9.20) ⑤开始音频驱动wm8978学习(因为在最后speex直接调用音频驱动的,所以有必要去了解)(add:2012.9.20) ⑥[https://github.com/lindabell/VoIP_RT_Thread/raw/master/APP/examples/5_media_mp3/wm8978.pdf](wm8978.pdf)(add:2012.9.22) ⑦[https://github.com/lindabell/VoIP_RT_Thread/raw/master/APP/examples/5_media_mp3/WAV%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F.pdf](WAV文件格式.pdf) (add:2012.9.24) ⑧终于可以在同一个程序里录音和播放了(add:2012.10.10) **2.移植speex语音压缩解压软件到realtouch,现实本地语音压缩与解压 (2012.10.20~)** ①[http://www.speex.org/](speex官网) (add:2012.10.20) ②[http://downloads.xiph.org/releases/speex/speex-1.2rc1.tar.gz](speex-1.2rc1.tar.gz) (add:2012.10.20) ③[http://www.speex.org/docs/manual/speex-manual.pdf](speex-manual.pdf) (add:2012.10.20) ④[http://www.speex.org/docs/api/speex-api-reference.pdf](speex-api-reference.pdf) (add:2012.10.20) ⑤[http://blog.csdn.net/lindabell/article/details/8100459](speex-manual翻译(转)) (add:2012.10.24) ⑥移植到win32 读WAV文件speex压缩、解压,保存到.WAV文件;目前声音很差应该和参数设置有问题(add:2012.11.3) ⑦把⑥的程序转到RTT里了,现在可以对wav文件进行speex压缩,并解压出wav格式。具体的工程在本帖子第4页可以下载(add:2012.12.25)
shaolin
2012-09-08
这家伙很懒,什么也没写!
这个项目很强,一定要顶起。有关开发过程中的问题可以提出来,我们也也会给予相应的支持。
bernard
2012-09-08
这家伙很懒,什么也没写!
这个挺好,VoIP不选择使用SIP或H.323吗?这部分也可以考虑移植一些标准的通信协议库,这些库也是面向嵌入式领域的。
lindabell
2012-09-08
这家伙很懒,什么也没写!
>这个挺好,VoIP不选择使用SIP或H.323吗?这部分也可以考虑移植一些标准的通信协议库,这些库也是面向嵌入式领域的。 --- 怕涉及的东西太多了,鸭梨太大了。 这个题目对我来说难度已经非常大了。
aozima
2012-09-08
调网络不抓包,调I2C等时序不上逻辑分析仪,就像电工不用万用表!多用整理的好的文字,比截图更省流量,还能在整理过程中思考。
小马过河,呵呵。 录音已有测试程序,打算稍微改进一下后再push上去,先PM您了。
prife
2012-09-09
这家伙很懒,什么也没写!
支持!
lindabell
2012-09-10
这家伙很懒,什么也没写!
呀,得到这么多大神的支持真的很高兴啊
lindabell
2012-09-10
这家伙很懒,什么也没写!
我也是个初学者,所以描述有不当的请指正(阅读时一定要带着批判的眼光对待)。 下面我就写流水账了 目前我采用realtouch里的5_media_mp3的例子来学习realtouch的音频播放;为什么选这个例子呢,因为这个例程能够直接演示(获得一些感性认识)。我们可以先估计一下它的大概流程,我估计大概有这个流程 1.读MP3文件 2.解码 3.发到音频驱动播放 4.结束 好了,我们到MP3.c找到void mp3(char* filename);看看和我们猜的是一样的吗? ``` /** 1.打开MP3文件 2.创建MP3解码器 3.设置获取MP3数据函数 4.MP3解码开始 5.MP3解码结束并删除解码器占用的资源 6.关闭文件 */ void mp3(char* filename) { int fd; struct mp3_decoder* decoder; fd = open(filename, O_RDONLY, 0); if (fd >= 0) { decoder = mp3_decoder_create(); //创建、分配内存、初始化decoder if (decoder != RT_NULL) { decoder->fetch_data = fd_fetch; //设置从文件取数据函数 decoder->fetch_parameter = (void*)fd; //设置传入的参数为打开的文件号(fd) current_offset = 0; while (mp3_decoder_run(decoder) != -1); //这里进行解码 /* delete decoder object */ mp3_decoder_delete(decoder); //解码结束删除decoder } close(fd); //最后关闭打开的文件 } } ``` 可以看出和我们猜的大概一样的 1.打开文件:这个就是打开MP3文件,这个具体是怎么工作咱就不管了(不是主要任务) 2.创建MP3解码器:这个得进去看看如下(就是为准备使用解码器做的一些准备) ``` /** 创建mp3解码器 1.定义一个解码器 2.分配内存给这个解码器 3.初始化解码器 */ struct mp3_decoder* mp3_decoder_create() { struct mp3_decoder* decoder; /* allocate object */ decoder = (struct mp3_decoder*) rt_malloc (sizeof(struct mp3_decoder)); if (decoder != RT_NULL) { mp3_decoder_init(decoder); } return decoder; } ``` 设置获取MP3数据函数:这个应该是软解MP3的底层函数,即是告诉解码器怎样去取数据(这里就去打开的文件读取数据),至于怎么去咱就不管了(先抓主要的,次要的先放着) MP3解码开始:这个才是这个函数里的重点,这里做了解码和把解码后的数据发送到音频驱动了。由于这个函数较大先放一会 5.MP3解码结束并删除解码器占用的资源:不解析了 6.关闭文件:一定要记得关闭文件 好了,咱再回到“MP3解码开始”这部分 ``` /** 1.解码器里的数据是否少于一定值,少于则把缓冲区填够 2.在缓冲区里查找同比字符(不知道是什么,先不管;应该就是一些协议之类的) 3.解码 4.判断解码成功与否(并进行错误处理) 5.获取上次设置的参数信息 6.修改成需要的参数(采样率) 7.处理解码后的数据(不知道为什么这样处理,先不理) 8.把数据发送到音频设备上播放 */ int mp3_decoder_run(struct mp3_decoder* decoder) { int err; rt_uint16_t* buffer; rt_uint32_t delta; RT_ASSERT(decoder != RT_NULL); // if ((decoder->read_ptr == RT_NULL) || decoder->bytes_left < 2*MAINBUF_SIZE) { if(mp3_decoder_fill_buffer(decoder) != 0) return -1; } // rt_kprintf("read offset: 0x%08x ", decoder->read_ptr - decoder->read_buffer); decoder->read_offset = MP3FindSyncWord(decoder->read_ptr, decoder->bytes_left); if (decoder->read_offset < 0) { /* discard this data */ rt_kprintf("outof sync, byte left: %d ", decoder->bytes_left); decoder->bytes_left = 0; return 0; } decoder->read_ptr += decoder->read_offset; delta = decoder->read_offset; decoder->bytes_left -= decoder->read_offset; if (decoder->bytes_left < 1024) { /* fill more data */ if(mp3_decoder_fill_buffer(decoder) != 0) return -1; } /* get a decoder buffer */ buffer = (rt_uint16_t*)sbuf_alloc(); decoder->bytes_left_before_decoding = decoder->bytes_left; err = MP3Decode(decoder->decoder, &decoder->read_ptr,(int*)&decoder->bytes_left, (short*)buffer, 0); //解码,把解码的数据放到buffer中 delta += (decoder->bytes_left_before_decoding - decoder->bytes_left); current_offset += delta; decoder->frames++; if (err != ERR_MP3_NONE) { switch (err) { case ERR_MP3_INDATA_UNDERFLOW: rt_kprintf("ERR_MP3_INDATA_UNDERFLOW "); decoder->bytes_left = 0; if(mp3_decoder_fill_buffer(decoder) != 0) { /* release this memory block */ sbuf_release(buffer); return -1; } break; case ERR_MP3_MAINDATA_UNDERFLOW: /* do nothing - next call to decode will provide more mainData */ rt_kprintf("ERR_MP3_MAINDATA_UNDERFLOW "); break; default: rt_kprintf("unknown error: %d, left: %d ", err, decoder->bytes_left); // skip this frame if (decoder->bytes_left > 0) { decoder->bytes_left --; decoder->read_ptr ++; } else { // TODO RT_ASSERT(0); } break; } /* release this memory block */ sbuf_release(buffer); } else { int outputSamps; /* no error */ MP3GetLastFrameInfo(decoder->decoder, &decoder->frame_info); /* set sample rate */ if (decoder->frame_info.samprate != current_sample_rate) { current_sample_rate = decoder->frame_info.samprate; rt_device_control(decoder->snd_device, CODEC_CMD_SAMPLERATE, ¤t_sample_rate); } /* write to sound device */ outputSamps = decoder->frame_info.outputSamps; if (outputSamps > 0) { if (decoder->frame_info.nChans == 1) { int i; for (i = outputSamps - 1; i >= 0; i--) { buffer[i * 2] = buffer[i]; buffer[i * 2 + 1] = buffer[i]; } outputSamps *= 2; } rt_device_write(decoder->snd_device, 0, buffer, outputSamps * sizeof(rt_uint16_t)); } else { /* no output */ sbuf_release(buffer); } } return 0; } ``` 以上就是播放MP3的流程来了。
shaolin
2012-09-10
这家伙很懒,什么也没写!
结果是什么样的呢?能够在 RealTouch 上正常播放 MP3?
lindabell
2012-09-10
这家伙很懒,什么也没写!
>结果是什么样的呢?能够在 RealTouch 上正常播放 MP3? --- 这个是realtouch里的例程,当然能播放mp3啦,我只是加一些解析而已
撰写答案
登录
注册新账号
关注者
0
被浏览
25.4k
关于作者
lindabell
这家伙很懒,什么也没写!
提问
9
回答
93
被采纳
0
关注TA
发私信
相关问题
1
[项目]搞个开源的硬件项目
2
硬件计划贴,及时更新,欢迎提意见
3
软件计划贴,及时更新,欢迎提意见::WMA,MOUNT,LWIP等问题急需解决.
4
MMS协议
5
定点的wma解压库-libwma
6
QQ群记录 [20090821]
7
STM32网络收音机PCB报名征集
8
第一版调试记录
9
第二版硬件讨论
10
RADIO项目相关模块规格--欢迎大家自己做板时规格与此兼容,减少重复劳动
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
8
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
3
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部