AirPlay是苹果公司推出的一套无线音乐解决方案,我们手里的iPhone、iPad甚至是Apple Watch等设备还有电脑上的iTunes都支持AirPlay,但是支持AirPlay功能的音响设备都是比较贵的,荷包扁扁的我自然是感觉买那么贵的音响实在是不合算。前两天突发奇想,如果STM32可以支持AirPlay的功能,那么不就可以让我享受一把无线音乐的自由自在了吗?于是马上登陆github搜了一下,发现还真有解决方案不过基本上所有的方案都是在linux或者windows上运行的,精挑细选之后选择了https://github.com/juhovh/shairplay这个AirPlay开源项目,主要是该代码是用C语言实现移植到stm32比较方便。
在开始之前我们有必要先了解一下AirPlay, AirPlay是苹果公司收购airtunes后升级airtunes的协议库,在airtunes增加了视频,照片的传输,完整的变为airplay非开源功能,实现随时随地的家庭音乐无线流媒体传输。AirPlay可以将iPhone 、iPad、iPod touch 等iOS 设备上的包括图片、音频、视频及镜像传输到支持AirPlay的设备中播放,AirPlay的实现过程中包含多个协议,其中有的协议是完全标准的, 有一部分协议进行了一些修改,有的则是完全私有的。
? Multicast DNS用于发布服务, 启动后, 在iOS的控制中心菜单中就能看到对应的设备;
? HTTP / RTSP / RTP 用于流媒体服务, 传输音视频数据, 进行播放控制等;
? NTP 时间同步;
? FairPlay DRM加密 完全私有的加密协议。
我们需要准备一部iphone手机并安装网易云音乐,W5500EVB开发板(stm32f103+W5500),PCM5102A音频模块。iPhone手机用来作为客户端搜索设备及发送音频数据,W5500EVB是WIZnet的开发板具有以太网功能用来作为服务器接收音频数据,开发板的操作可以参考www.w5500.com中的例程。PCM5102A音频模块是将解码后的音频数据进行播放。经过分析后我们要实现Airplay音频播放主要是实现以下三个方面:
1、 iPhone在网络中发现 W5500设备并建立连接
2、 W5500EVB接收并解码音频数据
3、 W5500EVB通过I2S接口将音频传送到PCM5102A音频模块
1、发现设备并建立连接
Airplay发现设备是基于mdns协议实现,iPhone与W5500EVB需要连入同一网络且W5500EVB要加入组播组224.0.0.251才可以接收mdns报文。W5500EVB收到iphone发出的querry查询报文后回复response报文,报文的内容可以参考文档《Unofficial AirPlay Protocol Specification》(http://nto.github.io/AirPlay.html),下方为MDNS设备发现代码:
1uint8 dns_query(uint8 s, uint8 * name,uint8* rname)
2 {
3 uint8 ip[4];
4 uint16 len, port;
5 switch (getSn_SR(s)) {
6 case SOCK_UDP:
7 if ((len = getSn_RX_RSR(s)) > 0) {
8 if (len > MAX_DNS_BUF_SIZE) {
9 len = MAX_DNS_BUF_SIZE;
10 }
11 len = recvfrom(s, BUFPUB, len, ip, &port);
12 len=dns_makequery(0,name,rname,BUFPUB,MAX_DNS_BUF_SIZE);
13 sendto(s, BUFPUB, len, DIP,DPORT);
14 len=dns_makeresponse(0,name,rname,BUFPUB,MAX_DNS_BUF_SIZE);
15 sendto(s, BUFPUB, len, DIP,DPORT);
16 }
17 break;
18 case SOCK_CLOSED:
19 setDIPR(s,DIP);/* 设置目标IP 224.0.0.251*/
20 setDHAR(s,DHAR);/*设置目标MAC 01:00:5e:00:00:FB*/
21 setDPORT(s,DPORT);/*设置目标端口5353*/
22 &nb