为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

01嵌入式IP网络语音通信[1]

2013-08-07 12页 pdf 254KB 75阅读

用户头像

is_217844

暂无简介

举报
01嵌入式IP网络语音通信[1] 北京信息科技大学 嵌入式 IP网络语音通信 - 1 - 光电学院电子信息工程专业 “嵌入式信息系统课程设计”任务书 题目 嵌入式 IP网络语音通信 主要 内容 学习和掌握构建基于 OMAP3530硬件平台和嵌入式 Linux软件开发环境的方法, 掌握嵌入式应用程序设计与开发手段,在此基础上通过 socket 网络编程实现基于嵌入 式 IP网络的双向语音通信。 设计 要求 ...
01嵌入式IP网络语音通信[1]
北京信息科技大学 嵌入式 IP网络语音通信 - 1 - 光电学院电子信息专业 “嵌入式信息系统课程”任务书 目 嵌入式 IP网络语音通信 主要 内容 学习和掌握构建基于 OMAP3530硬件平台和嵌入式 Linux软件开发环境的方法, 掌握嵌入式应用程序设计与开发手段,在此基础上通过 socket 网络编程实现基于嵌入 式 IP网络的双向语音通信。 设计 要求 基本要求: 1、在嵌入式系统环境下,实现本地语音录放; 2、通过 Socket网络编程实现 IP网络双向语音传输。 扩展要求:选作 1个或多个功能,也可以自行设计其它扩展功能。 1、实现基于 G.711的语音编码(A律 13折线); 2、网络性能及分组大小对通信质量的影响; 3、实现基于 G.721标准的语音编码(ADPCM); 4、实现基于 G.723.1标准的语音编码(码激励线性预测编码)。 主要 仪器 设备 1、OMAP3530嵌入式开发系统 1套 2、计算机 1台,安装 Linux操作系统及 arm-linux交叉编译工具 3、耳麦 1个 4、网线 2根,IP地址 2个 课程设计进度计划(起止时间、工作内容) 第 1周 掌握构建嵌入式 Linux开发环境及开发应用程序的基本方法;理解所选题目要求, 学习相关知识,搭建相应软件和硬件环境; 第 2周 完成基本要求,实现本地声音录放及嵌入式网络环境下的语音通信; 第 3周 进一步完善功能并进行扩展要求设计,现场检查、答辩; 课程设计期间的其它时间实验室也一直开放,需要实验的同学在遵守实验室管理规定的条件 下可以随时进行实验。课程设计报告要求在课程设计结束后一周内提交。 课程设计开始日期 2010-12-6 课程设计完成日期 2010.12.19 课程设计实验室名称 嵌入式网络系统实验室 地 点 实验楼 501-1 课程设计专题网站 http://59.64.74.111/ 资料和软件下载地址 ftp://59.64.74.111/ 北京信息科技大学 嵌入式 IP网络语音通信 - 2 - 第一章 ALSA语音编程 一、数字音频 音频信号是一种连续变化的模拟信号,但计算机只能处理和记录二进制的数字信 号,由自然音源得到的音频信号必须经过一定的变换,成为数字音频信号之后,才能送 到计算机中作进一步的处理。 数字音频系统通过将声波的波型转换成一系列二进制数据,来实现对原始声音的重 现,实现这一步骤的设备常被称为模/数转换器(A/D)。A/D转换器以每秒钟上万次的 速率对声波进行采样,每个采样点都记录下了原始模拟声波在某一时刻的状态,通常称 之为样本(sample),而每一秒钟所采样的数目则称为采样频率,通过将一串连续的样 本连接起来,就可以在计算机中描述一段声音了。对于采样过程中的每一个样本来说, 数字音频系统会分配一定存储位来记录声波的振幅,一般称之为采样分辩率或者采样精 度,采样精度越高,声音还原时就会越细腻。 数字音频涉及到的概念非常多,对于在 Linux下进行音频编程的程序员来说,最重 要的是理解声音数字化的两个关键步骤:采样和量化。采样就是每隔一定时间就读一次 声音信号的幅度,而量化则是将采样得到的声音信号幅度转换为数字值,从本质上讲, 采样是时间上的数字化,而量化则是幅度上的数字化。下面介绍几个在进行音频编程时 经常需要用到的技术指标: 1、采样频率 采样频率是指将模拟声音波形进行数字化时,每秒钟抽取声波幅度样本的次数。采 样频率的选择应该遵循奈奎斯特(Harry Nyquist)采样理论:如果对某一模拟信号进行 采样,则采样后可还原的最高信号频率只有采样频率的一半,或者说只要采样频率高于 输入信号最高频率的两倍,就能从采样信号系列重构原始信号。正常人听觉的频率范围 大约在 20Hz~20kHz之间,根据奈奎斯特采样理论,为了保证声音不失真,采样频率应 该在 40kHz左右。常用的音频采样频率有 8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、 44.1kHz、48kHz等,如果采用更高的采样频率,还可以达到 DVD的音质。 2、量化位数 量化位数是对模拟音频信号的幅度进行数字化,它决定了模拟信号数字化以后的动 态范围,常用的有 8位、12位和 16位。量化位越高,信号的动态范围越大,数字化后 的音频信号就越可能接近原始信号,但所需要的存贮空间也越大。 3、声道数 声道数是反映音频数字化质量的另一个重要因素,它有单声道和双声道之分。双声 道又称为立体声,在硬件中有两条线路,音质和音色都要优于单声道,但数字化后占据 的存储空间的大小要比单声道多一倍。 二、声卡驱动 出于对安全性方面的考虑,Linux下的应用程序无法直接对声卡这类硬件设备进行 操作,而是必须通过内核提供的驱动程序才能完成。在 Linux上进行音频编程的本质就 是要借助于驱动程序,来完成对声卡的各种操作。对硬件的控制涉及到寄存器中各个比 特位的操作,通常这是与设备直接相关并且对时序的要求非常严格,如果这些工作都交 北京信息科技大学 嵌入式 IP网络语音通信 - 3 - 由应用程序员来负责,那么对声卡的编程将变得异常复杂而困难起来,驱动程序的作用 正是要屏蔽硬件的这些底层细节,从而简化应用程序的编写。 目前 Linux下常用的声卡驱动程序主要有两种:OSS和 ALSA。最早出现在 Linux 上的音频编程接口是 OSS(Open Sound System),它由一套完整的内核驱动程序模块 组成,可以为绝大多数声卡提供统一的编程接口。OSS出现的历史相对较长,这些内核 模块中的一部分(OSS/Free)是与 Linux内核源码共同免费发布的,另外一些则以二进 制的形式由 4Front Technologies公司提供。由于得到了商业公司的鼎力支持,OSS已经 成为在 Linux下进行音频编程的事实标准,支持 OSS的应用程序能够在绝大多数声卡 上工作良好。 虽然 OSS已经非常成熟,但它毕竟是一个没有完全开放源代码的商业产品,ALSA (Advanced Linux Sound Architecture)恰好弥补了这一空白,它是在 Linux下进行音频 编程时另一个可供选择的声卡驱动程序。ALSA除了像 OSS那样提供了一组内核驱动 程序模块之外,还专门为简化应用程序的编写提供了相应的函数库,与 OSS提供的基 于 ioctl的原始编程接口相比,ALSA函数库使用起来要更加方便一些。ALSA的主要特 点有: · 支持多种声卡设备 · 模块化的内核驱动程序 · 支持 SMP和多线程 · 提供应用开发函数库 · 兼容 OSS应用程序 ALSA和 OSS最大的不同之处在于 ALSA是由志愿者维护的自由项目,而 OSS则 是由公司提供的商业产品,因此在对硬件的适应程度上 OSS要优于 ALSA,它能够支 持的声卡种类更多。ALSA虽然不及 OSS运用得广泛,但却具有更加友好的编程接口, 并且完全兼容于 OSS,对应用程序员来讲无疑是一个更佳的选择。 三、 ALSA体系 ALSA 标准是一个先进的 linux 声音体系。它包含内核驱动集合,API 库和工具对 Linux 声音进行支持。ALSA 包含一系列内核驱动对不同的声卡进行支持,还提供了 libasound 的 API 库。用这些进行写程序不需要打开设备等操作,所以编程人员在写程 序的时候不会被底层的东西困扰。与此相反 OSS/Free 驱动在内核层次调用,需要指定 设备名和调用 ioctl。为提供向后兼容,ALSA 提供内核模块模仿 OSS/Free 驱动,所以 大多数的程序不需要改动。 ALSA 拥有调用插件的能力对新设备提供扩展,包括那些 用软件模拟出来的虚拟设备。 ALSA 还提供一组命令行工具包括 mixer, sound file player 和工具控制一些特别的声卡的特别的作用。 ALSA API 被主要分为以下几种接口: l 控制接口:提供灵活的方式管理注册的声卡和对存在的声卡进行查询。 l PCM接口:提供管理数字音频的捕捉和回放。 l 原始 MIDI 接口: 支持 MIDI (Musical Instrument Digital Interface), 一种标准 电子音乐指令集。 这些 API 提供访问声卡上的 MIDI 总线。这些原始借口直 接工作在 The MIDI 事件上,程序员只需要管理协议和时间。 北京信息科技大学 嵌入式 IP网络语音通信 - 4 - l 记时接口: 为支持声音的同步事件提供访问声卡上的定时器。 l 音序器接口:一个比原始MIDI接口高级的MIDI编程和声音同步高层接口。它 可以处理很多的MIDI协议和定时器。 l 混音器接口:控制发送信号和控制声音大小的声卡上的设备。 声卡的缓存和数据的传输: 一块声卡有一个声卡内存用来存储记录的样本。当它被写满时就产生中断。内核驱 动就使用 DMA将数据传输到内存中。同样地,当在播放时就将内存中的声音样本使用 DMA传到声卡的内存中! 声卡的缓存是环状的,这里只讨论应用程序中的内存结构:ALSA将数据分成连续 的片段然后传到按单元片段传输。 四、典型的声音程序结构: n open interface for capture or playback n set hardware parameters n (access mode, data format, channels, rate, etc.) n while there is data to be processed: n read PCM data (capture) n or write PCM data (playback) n close interface 五、ALSA交叉编译 1、下载源代码包 官方网址位于 http://www.alsa-project.org/main/index.php/Main_Page,可下载最新的源 代码。本地源文件位于/home/user/Project/audio目录下。 2、进入工作目录并解压缩 Host # cd /home/user/Project/audio 北京信息科技大学 嵌入式 IP网络语音通信 - 5 - 3、编译 alsa-lib 编译生成的程序和库位于/home/user/build目录下。 6、编译 alsa-utils 7、测试编译得到的 alsa工具包 拷贝编译得到的/home/user/build目录下各个文件夹里的内容到 SD卡的 EXT3文件 系统中/usr/local中。 8、启动开发板系统并测试 到开发板系统的/usr/local/build/bin目录下测试 alsa-utils工具程序。下载 wav文件到 开发板上,测试 wav文件可以在 Linux或者 windows下用录音机自行生成。 9、结果 可在开发板上听到声音,有兴趣的同学可以自己生成不同格式的 wav文件测试。程 序原理可以看 aplay的源代码。 六、编译采集和回放程序 测试程序位于 mini_app_pc和 mini_app_arm目录下,根据系统环境修改 Rules.make 和Makefile文件分别得到 PC端和 ARM端可执行程序,分别进行测试并分析程序。 Host # tar xvf alsa-lib-1.0.23.tar.bz2 Host # tar xvf alsa-utils-1.0.23.tar.bz2 Host # cd alsa-lib-1.0.23 Host# ./configure --prefix=/home/user/build --host=arm-none-linux-gnueabi --disable-python Host# make Host# sudo make install Host # cd alsa-utils-1.0.20 Host # ./configure --prefix=/home/user/build --host=arm-none-linux-gnueabi --disable-xmlto --with-alsa-prefix=/home/user/build/lib --with-alsa-inc-prefix=/home/user/build/include --disable-alsamixer -- disable-nls Host# make Host#sudo make install Host #sudo mkdir /media/EXT3/usr/local Host# cd /home/user/ Host#sudo cp -rf build /media/EXT3/usr/local 北京信息科技大学 嵌入式 IP网络语音通信 - 6 - 第二章 网络传输 socket编程指南 一、编程原理 1、套接口的功能 套接口本质上提供了进程间通信的端点。进程通信之前,双方必须首先各自创建一 个套接口。每个套接口拥有一个本地唯一的套接口描述符,由操作系统分配。套接口是 面向 C/S模型设计的。 2、套接口的两种类型 1)流套接口(SOCKET_STREAM): 流套接口提供了可靠的,面向连接的通信流。它使用 TCP协议来保证数据传输的质 量。有关 TCP 协议的内容请参考级网络讲义传输层部分。 2)数据报套接口(SOCK_DGRAM): 数据报套接口定义了一种面向无连接的服务,数据通过相互独立的报文进行传输, 是无序的,不保证可靠、无差错。数据报套接口使用 UDP协议。有关 UDP协议的内容 请参考网络讲义传输层部分。 其它套接口类型请查阅相关网络编程的资料。 3、面向连接和无连接的套接口的#工作# 这两种类型的工作流程请参考网络讲义的 SOCKET 编程部分。服务器端程序的套 接口需要系统调用 bind 绑定,而对于客户端程序则不是必需的,一般不用绑定,系统 会自动选择一个 1024(不包括 1024)以外未被使用的端口号。因为我们不在乎客户端 程序会使用哪个端口,但我们在乎服务器端的哪个端口能被客户端程序连接。 二、编程接口 1、socket函数 调用 socket()分配一个套接口,该函数返回一个本地唯一的套接口描述符。Socket 声 明如下: int socket (int domain, int type, int protocol); 其中: 北京信息科技大学 嵌入式 IP网络语音通信 - 7 - 第一个参数 domain 指定使用何种地址类型,一般是 AF_INET,其它值可在 /usr/include/sys/socket.h中找到。 第二个参数 type 的值一般使用如下两种: SOCK_STREAM------提供了一个可靠的的顺序的双向连接 SOCK_DGRAM ------提供了无连接不可靠的连接 其它值可在/usr/include/sys/types.h查看。 第三个参数 protocol 设为 0 即可。 如果调用成功,返回一个套接口描述符,即一个整型值;如果发生错误,返回-1, 全局变量 errno将被设置为错误代码。(请参考 man 3 perror。) 更详细信息请 man 2 socket 一下。 2、bind函数 bind()函数将你刚刚分配的一个套接口与一个端口号绑定,当然,你可以指定在范 围 1025~65535(2^16-1)内的任意数值。1~1024 的端口号保留系统使用。那什么时候 需要绑定呢?当你需要进行端口监听 listen 操作, 等待接受一个连接请求的时候,就要 进行端口绑定。bind()的声明如下: int bind (int sockfd, const struct sockaddr *my_addr,int addrlen); 第一个参数 sockfd是由 socket()函数返回的套接口描述符。 第二个参数 my_addr是一个指向 struct sockaddr 的指针。该指针指向的变量包含有关 的地址信息:名称、端口和 IP地址。struct sockddr请参考数据结构部分。 第三个参数 addrlen是数据结构 sockaddr的长度,可设置为 sizeof(struct sockaddr)。 如果发生错误,返回-1,全局变量 errno将被设置为错误代码。 更多请参考 man 2 bind。 3、listen函数 对于服务器程序,当把套接口与某一端口绑定后,可调用 listen()监听该端口是否有 连接请求。该函数的声明如下: int listen (int sockfd,int backlog); 第一个参数 sockfd是前面调用 bind()绑定后的套接口描述符。 第二个参数 backlog是连接请求队列的最大请求连接数。 如果发生错误,返回-1,全局变量 errno将被设置为错误代码。 更多请参考 man 2 listen 。 4、accept函数 与 listen 一样,accept()也是用于服务器程序。accept() 用于接收远程连接请求,用 于建立基于 TCP的流套接口的连接。其声明如下: 北京信息科技大学 嵌入式 IP网络语音通信 - 8 - int accept (int sockfd, struct sockaddr *addr, socklen_t *addrlen); 第一个参数 sockfd是被监听的套接口的描述符。 第二个参数 addr 是无类型指针,一般指向一个 struct sockaddr_in 结构的变量;该 变量存储有远程连接过来的计算机信息。 第三个参数 addrlen是一个指向整型变量的指针。该整型变量设置了 their_addr所能 容纳的最大字节数,这个变量的值一般是 sizeof(struct sockaddr_in)。 如果调用成功,accept 返回一个新的套接口描述符,用于与远程进程通信,原来的 套接口描述符仍然在原来的端口的 listen()上;如果调用失败,返回-1,全局变量 errno 被设为错误代码。 更多请看 man 2 accpet 。 5、connect函数 系统调用 connect 用于将本地的套接口与远程的套接口连接起来,完成建立基于 TCP 的流套接口的连接。其声明如下: int connect (int sockfd, const struck sockaddr *server_addr, int addrlen); 第一个参数 sockfd 是套接口描述符,由 socket()函数返回。 第二个参数 server_adddr是指针,指向存储有远程计算机的 IP地址和端口号信息的 结构。 第三个参数 addrlen是数据结构的大小,应该是 sizeof(struct sockaddr)。 如果调用发生错误,返回-1,全局变量 errno将会存储错误代码。 更多请看 man 2 connect 。 6、send和 recv函数 这两个函数是通过连接的流套接口进行通信的函数。 send 是用于通过套接口向其它进程发送数据的函数,其声明如下: ssize_t send(int s, const void *buf, size_t len, int flags); 第一个参数 s是必须是已经连接到远程计算机的一个端口上的套接口描述符。 第二个参数 buf是指向内存块的指针,此内存块用来存储要发送的信息。 第三个参数 len表示发送信息的长度。 第四个参数 flag是操作标志,一般设为 0。 如果调用成功,返回发送出去的数据的真正长度;如果失败,返回-1,全局变量 errno 存储错误代码。 更多请看 man 2 send 。 Recv是用于接收从已经连接的套接口传来的数据,其声明如下: 北京信息科技大学 嵌入式 IP网络语音通信 - 9 - ssize_t recv(int s, void *buf, size_t len, int flags); 第一个参数 s必须是已经连接到远程计算机的端口上的套接口描述符。 第二个参数 buf是指向内存块的指针,此内存块用于存储接收到的数据。 第三个参数 len是 buf指向的内存块的大小。 第四个参数 flags是操作标志,一般设为 0。 如果调用成功,返回接受到的实际数据长度;如果调用失败,返回-1,全局变量 errno 存储错误代码。 更多请看 man 2 recv 。 7、sendto函数和 recvfrom函数 这两个函数是进行无连接的 UDP 通信时使用的。因为传输之前没有建立连接,所 以发送数据时,要知道远程主机的 IP地址和端口号。 1)sendto函数 用于接收数据。其声明如下: ssize_tsendto(ints,constvoid*buf,size_t len, int flags, const struct sockaddr *to, socklen_t tolen); sendto与 send函数基本上一致,只是多加了两个存储有远程主机地址信息的参数。 第一个参数 s是 socket()调用返回的套接口描述符。 第二个参数 buf是个指针,指向要发送的数据的地址。 第三个参数 len是要发送数据的长度。 第四个参数 flags是操作标志,一般设为 0。 第五个参数 to是个指针,指向存储有远程主机地址信息的数据结构。 第六个参数 tolen是数据结构 sockaddr 的大小,为 sizeof(struct sockaddr)。 如果调用成功,返回发送的数据的实际长度;如果失败,返回-1,全局变量 errno 存储错误代码。 更多请看 man 2 sendto. 2)recvfrom函数 同样,recvfrom与 recv 也基本一致。其声明如下: ssize_t recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); 第一个参数 s是 socket()调用返回的套接口描述符。 第二个参数 buf是个指针,指向能存储数据的内存缓冲区。 第三个参数 len是缓冲区的最大长度。 第四个参数 flags是操作标志,一般设为 0。 第五个参数 from是个指针,指向存储源主机地址信息的数据结构 struct sockaddr。 第六个参数 fromlen是个整型指针,该整型变量的值为 sizeof(struct sockaddr)。 如果调用成功,返回接收到的数据字节数;如果失败,返回-1,全局变量 errno 存储错 误代码。 更多请看 man 2 recvfrom 。 北京信息科技大学 嵌入式 IP网络语音通信 - 10 - 8、close函数 参考语音编程部分。 9、gethostbyname函数和 herror函数 1)gethostbyname函数 gethostbyname() 接受点分形式的 IP 地址或实际的主机名,执行域名服务器查 询并返回一个结构指针,这个结构包含了 sockaddr_in 结构所期望的那种形式的 IP 地址数据。其声明如下: struct hostent *gethostbyname(const char *name); 如果调用成功,返回一个结构指针;如果失败,返回一个 NULL指针,全局变 量 h_errno存储错误代码。 2)herror函数 void herror(const char *s); herror()函数是在标准错误输出上打印与变量 h_error的当前值有关的错误信息。 更多请看 man 3 gethostbyname 。 10、bzero函数 bzero()将一段内存的内容清零。其声明如下: void bzero(void *s, size_t n); 第一个参数 s是指向一个内存块的指针。 第二个参数 n是要清零的内存块大小。 该函数无返回值。 更多请看 man 3 bsero 。 11、fgets函数 fgets()从文件中读取一个字符串并存到指定的内存空间,直到遇到换行符、读到文 件尾或者已读入了 size-1个字符为止,最后加上 NULL作为字符串结束。其声明如下: char *fgets(char *s, int size, FILE *stream); 第一个参数 s是一个指向一个内存块的指针,该内存块用于存储从 stream读出的数 据。 如果调用成功,返回指针 s;如果失败,返回 NULL。 更多请看 man 3 fgets 。 12、转换函数:htonl(), htons(), inet_ntoa() 1)htonl 北京信息科技大学 嵌入式 IP网络语音通信 - 11 - htonl()将参数指定的 32位主机字节顺序数据转换成网络字节顺序。其声明如下: uint32_t htonl(uint32_t hostlong); 参数是一个主机字节顺序的 32位数据。该函数返回对应的网络字节顺序。 更多请看 man 3 htonl 。 2)htons htons()与 htonl()相似,用来将 16位的主机字节顺序的数据转换成网络字节顺序。 其声明如下: uint16_t htons(uint16_t hostshort); 参数指定要转换的 16位数据。该函数返回对应的网络字节顺序的数据。 更多请看 man 3 htons 。 3)inet_ntoa 其声明如下: char *inet_ntoa (srtuct in_addr in); 函数 inet_ntoa()将网络字节顺序的 Internet主机地址 in转换成标准的点分形式的 地址字符串。 如果调用成功,返回一个字符串指针:如果失败,返回 NULL。 更多请看 man 3 inet_ntoa 。 13、以上编程接口函数用到的数据结构 struct sockaddr{ unsigned short sa_family; char sa_data[14]; }; sa_family是地址族,一般是 AF_INET. sa_data包含了远程主机的地址、端口号和套接口的数目,它里面的数据是杂溶在一 起的。 该数据结构必须被分配并作为 bind()的第二个参数,但在程序中不能直接访问。 为了访问 struct sockaddr,建立了另外一个相似的数据结构 struct sockaddr_in{ short int sin_family; unsigned short int sin_port; struct in_addr sin_addr; unsigned char sin_zero[8]; }; sin_family与 sa_family相同,设为 AF_INET。 sin_port是端口号。 sin_addr是 IP地址。 sin_zero[8]是为了使 struct sockaddr_in和 struct sockaddr在内存中具有相同的大小, 使用 struct sockaddr_in 时要把 sin_zero[8]全部设成 0(使用 bzero()函数或 memset())。 需要注意的是 sin_port 和 sin_addr一定要是网络字节顺序。 北京信息科技大学 嵌入式 IP网络语音通信 - 12 - 14、对字节顺序的简单解释 因为每一个机器内部对变量的字节顺序不同(有的高位在前,地位在后,而有的地 位在前,高位在后。),而网络传输的数据一定要有一个统一的顺序。所以一定要对内部 机器字节顺序和网络字节顺序不同的机器进行数据的转换。对与内部机器字节顺序和网 络字节顺序相同的,也要调用转换函数,但要不要转换由转换函数自己决定。 struct in_addr{ unsigned long s_addr; }; struct hostent{ char *h_name; char * *h_aliases; int h_addrtype; in h_length; char **h_addr_list; /* for backward compatibility */ }; #define h_addr h_addr_list[0] h_name是这个主机的正式名字。 h_aliases是一个以 NULL(空字符)结尾的数组,存储了主机的备用名字。 h_addrtype是返回地址的类型,一般是 AF_INET. h_length是地址的字节长度。 h_addr_list是一个以 0结尾的数组,存储了主机的网络地址。 三、示例程序 Socket示例程序位于/home/user/Project/audio/目录下,或者可以到 ftp://59.64.74.111/10embedded/ 目录下载。
/
本文档为【01嵌入式IP网络语音通信[1]】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索