﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-牵着老婆满街逛-随笔分类-文章收藏</title><link>http://www.cppblog.com/tx7do/category/1449.html</link><description>严以律己,宽以待人. 三思而后行.&lt;/br&gt;
GMail/GTalk: yanglinbo#google.com;&lt;/br&gt;
MSN/Email: tx7do#yahoo.com.cn;&lt;/br&gt;
QQ: 3 0 3 3 9 6 9 2 0 .</description><language>zh-cn</language><lastBuildDate>Tue, 15 Jan 2013 08:47:43 GMT</lastBuildDate><pubDate>Tue, 15 Jan 2013 08:47:43 GMT</pubDate><ttl>60</ttl><item><title>cocos2dx 内存管理</title><link>http://www.cppblog.com/tx7do/archive/2012/12/15/196327.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Sat, 15 Dec 2012 07:18:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/12/15/196327.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/196327.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/12/15/196327.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/196327.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/196327.html</trackback:ping><description><![CDATA[<strong style="color: red">转载自：</strong><a style="color: red" href="http://blog.csdn.net/ring0hx/article/details/7946397"><strong>http://blog.csdn.net/ring0hx/article/details/7946397</strong></a><a href="http://blog.csdn.net/ring0hx/article/details/7946397"><strong><br /></strong></a><br />
<div style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 16px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">cocos2dx的内存管理移植自Objective-C， 对于没有接触过OC的C++开发人员来说是挺迷惑的。不深入理解内存管理是无法写出好的C++程序的，我用OC和cocos2dx也有一段时间了，在此总结一下，希望对想用cocos2dx开发游戏的朋友有所帮助。</div>
<div style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">
<div style="font-size: 16px"><br /></div>
<div style="font-size: 16px">C++的动态内存管理一般建议遵循谁申请谁释放的原则，即谁通过new操作符创建了对象，谁就负责通过delete来释放对象。如果对象的生命周期在一个函数内，这很容易做到，在函数返回前delete就行了。但一般我们在函数中new出来的对象的生命周期都会超出该函数体(例如作为函数的返回值)，否则我们可以直接在栈上创建对象，不需要使用动态内存，也省去了内存管理的麻烦(当然大对象是不适合在栈上分配的)。如果对象的生命周期超出了创建对象的函数，我们就很难再遵循谁申请谁释放的原则了，我们必须在函数外的某个合适的地方释放对象，如果这个对象同时被多个对象引用，问题就很复杂了，必须保证所有该对象的引用者都不再需要它了才可以释放，在实际使用中这点是很难保证的。于是，各种内存管理技术应运而生了：垃圾回收器，智能指针，引用计数...... cocos2dx移植于Objective-C，因此和OC一样使用了比较原始的引用计数的方法来管理内存。</div>
<div style="font-size: 16px"><br /></div>
<div style="font-size: 16px">cocos2dx通过CCObject和CCPoolManager来实现内存管理。所有使用cocos2dx引用计数机制的类都必须派生自CCObject。CCObject有一个计数器成员变量m_uReference，当CCObject被构造时m_uReference=1，表示该对象被引用1次。CCObject的<span style="color: rgb(17,17,17)">retain方法可以使计数器加1，release方法可以使计数器减1。当计数器减到0时release方法会通过delete this来销毁自己。</span></div>
<div style="font-size: 16px"><span style="color: rgb(17,17,17)"><br /></span></div>
<div style="font-size: 16px"><span style="color: rgb(1,1,1)"><strong>手动内存管理</strong></span></div>
<div style="font-size: 16px"><span style="color: rgb(17,17,17)">使用retain和release，我们可以手动管理内存, 通过new 创建的对象，使用release来释放。 
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /><span style="color: #000000">CCObject&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">obj</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;CCObject();<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /><img src="http://www.cppblog.com/Images/dot.gif"  alt="" />&nbsp;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />obj</span><span style="color: #000000">-&gt;</span><span style="color: #000000">release();</span></div></span>和new\delete需配对使用一样，new\release也要配对使用才可确保内存被释放。有人会说这个把delete换成release有意义吗？需要注意的是这个的release并不等同于delete，release只是表示引用计数减1，并不是真正销毁obj所占用的内存。只有当obj的引用计数为0时内存才会被销毁。下面的代码就展示了release和delete不同：</div><span style="font-size: 16px"></span>
<div><span style="color: rgb(255,0,0)">
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /><span style="color: #000000">CCArray&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">array&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;CCArray::array();<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />CCObject&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">obj&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;CCObject();</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;m_uReference=1</span><span style="color: #008000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">array</span><span style="color: #000000">-&gt;</span><span style="color: #000000">addObject(obj);&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;CCArray的addObject方法会自动调用obj的retain方法，使引用计数加1，表示拥有obj，此时m_uReference=2</span><span style="color: #008000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">obj</span><span style="color: #000000">-&gt;</span><span style="color: #000000">release();&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;这里的release和new配对，obj引用计数减1，但是并不会释放obj,&nbsp;此时m_uReference=1;</span><span style="color: #008000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">obj</span><span style="color: #000000">-&gt;</span><span style="color: #000000">doSomething();&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;在release之后我们依然可以正常使用obj，它并没有被释放</span><span style="color: #008000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">array</span><span style="color: #000000">-&gt;</span><span style="color: #000000">removeObject(obj);&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">当我们把obj从CCArray中移除时，CCArray会自动调用obj的release，此时m_uReference=0,&nbsp;obj被销毁</span><span style="color: #008000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">obj</span><span style="color: #000000">-&gt;</span><span style="color: #000000">doSomething();&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;错误，obj已经被销毁</span></div>对于手动内存管理，我们需遵循new/release，retain/release配对使用的原则，谁new，谁release；谁retain，谁release。</span>new出来的对象如果是要加入到cocos2dx集合中，添加完后一定不要忘记release，集合类已经为你retain了对象，你还是要为你的new配对release一次，否则当这个对象从集合中移除时不会被正确销毁。 
<div><br /></div>
<div style="font-size: 16px"><strong>自动内存管理</strong></div>
<div style="font-size: 16px">手动内存管理似乎比new/delete更麻烦，而且并没有解决一开始我们提到的函数内创建的对象的生命周期超出函数怎么办的问题。new和release需配对使用，那在函数内创建的对象返回前我们需要调用一次release，在这之前如果我们没有把对象加入到什么集合中，对象就被销毁了，和使用new/delete是一样的。自动内存管理就可以解决这个问题。CCObject有一个autorelease方法，如果一个对象在用new关键字创建之后调用了autorelease，我们就不必关心它的释放问题。CCPoolManager会在游戏的每一帧结束后自动释放这些autorelease的对象。CCPoolManager其实依然是通过引用计数来管理对象生命周期的，它里面有一个CCAutoreleasePool，我们调用CCObject的autorelease就是把自己加入到CCAutoreleasePool的对象数组里面。当每一帧结束的时候，CCPoolManager会将对象从数组中移除，如果这时候对象的引用计数为0，对象就自然被释放了。<span style="color: rgb(227,0,0)">对于用new关键字创建之后调用了autorelease的对象，不需要再release一次。</span></div>
<div style="font-size: 16px"><br /></div>
<div style="font-size: 16px">cocos2dx中的大部分对象都可以通过静态工厂方法来创建出这种会自动释放的对象，这是cocos2dx的一条规则，我们自己实现的类最好也遵循这样的规则，以免引起其他开发人员误会。如果一个对象是通过类的静态方法创建而不是new出来的，我们就不需要release它。</div>
<div><br /></div>
<div style="font-size: 16px">其实这里的自动并没有我们想得那么好，对于像C#，Java这种托管语言，虚拟机为你完成了所有内存管理工作，程序员完全从内存分配和释放中解脱了出来。cocos2dx的autorelease只不过每帧结束后自动在为我们释放了一次对象，<span style="color: rgb(255,0,0)">如果我们希望创建的对象在下一帧仍然可以使用，我们需要显式地retain一下这个对象或者把对象加入到集合中(集合会帮我们retain一次)</span>。既然retain了，我们还是不能忘记在适当的地方release。比较常见的用法是创建一个autorelease对象作为类成员变量，我们在通过静态方法得到实例的指针后除了赋值给类成员，还要retain一次，然后在类的析构函数中release一次。如果没有retain，以后使用该成员的时候就会因为对象被销毁而发生内存访问错误，这是新手很容易遇到的陷阱。</div></div></div><img src ="http://www.cppblog.com/tx7do/aggbug/196327.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-12-15 15:18 <a href="http://www.cppblog.com/tx7do/archive/2012/12/15/196327.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>select 效率问题</title><link>http://www.cppblog.com/tx7do/archive/2012/12/13/196222.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 13 Dec 2012 11:00:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/12/13/196222.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/196222.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/12/13/196222.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/196222.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/196222.html</trackback:ping><description><![CDATA[<div><strong style="color: red">转载自：</strong><a style="color: red" href="http://blog.csdn.net/bulkinsert/article/details/6916510"><strong>http://blog.csdn.net/bulkinsert/article/details/6916510</strong></a><br />
<br />
<div style="text-align: left; widows: 2; text-transform: none;text-indent: 0px; margin: 20px 0px 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" id="article_content" class="article_content">&nbsp;很多人不知道SQL语句在SQL SERVER中是如何执行的，他们担心自己所写的SQL语句会被SQL SERVER误解。比如：&nbsp;<br />
<br />
select * from table1 where name='zhangsan' and tID &gt; 10000&nbsp;&nbsp;<br />
<br />
和执行:&nbsp;&nbsp;<br />
<br />
select * from table1 where tID &gt; 10000 and name='zhangsan'&nbsp;&nbsp;<br />
<br />
一些人不知道以上两条语句的执行效率是否一样，因为如果简单的从语句先后上看，这两个语句的确是不一样，如果tID是一个聚合索引，那么后一句仅仅从表的10000条以后的记录中查找就行了；而前一句则要先从全表中查找看有几个name='zhangsan'的，而后再根据限制条件条件tID&gt;10000来提出查询结果。&nbsp;&nbsp;<br />
<br />
事实上，这样的担心是不必要的。SQL SERVER中有一个&#8220;查询分析优化器&#8221;，它可以计算出where子句中的搜索条件并确定哪个索引能缩小表扫描的搜索空间，也就是说，它能实现自动优化。&nbsp;&nbsp;<br />
<br />
虽然查询优化器可以根据where子句自动的进行查询优化，但大家仍然有必要了解一下&#8220;查询优化器&#8221;的工作原理，如非这样，有时查询优化器就会不按照您的本意进行快速查询。&nbsp;&nbsp;<br />
<br />
在查询分析阶段，查询优化器查看查询的每个阶段并决定限制需要扫描的数据量是否有用。如果一个阶段可以被用作一个扫描参数（SARG），那么就称之为可优化的，并且可以利用索引快速获得所需数据。&nbsp;&nbsp;<br />
<br />
SARG的定义：用于限制搜索的一个操作，因为它通常是指一个特定的匹配，一个值得范围内的匹配或者两个以上条件的AND连接。形式如下：&nbsp;&nbsp;<br />
<br />
列名 操作符 &lt;常数 或 变量&gt;&nbsp;&nbsp;<br />
<br />
或&nbsp;&nbsp;<br />
<br />
&lt;常数 或 变量&gt; 操作符列名&nbsp;&nbsp;<br />
<br />
列名可以出现在操作符的一边，而常数或变量出现在操作符的另一边。如：&nbsp;&nbsp;<br />
<br />
Name=&#8217;张三&#8217;&nbsp;&nbsp;<br />
<br />
价格&gt;5000&nbsp;&nbsp;<br />
<br />
5000&lt;价格&nbsp;&nbsp;<br />
<br />
Name=&#8217;张三&#8217; and 价格&gt;5000&nbsp;&nbsp;<br />
<br />
如果一个表达式不能满足SARG的形式，那它就无法限制搜索的范围了，也就是SQL SERVER必须对每一行都判断它是否满足WHERE子句中的所有条件。所以一个索引对于不满足SARG形式的表达式来说是无用的。&nbsp;&nbsp;<br />
<br />
介绍完SARG后，我们来总结一下使用SARG以及在实践中遇到的和某些资料上结论不同的经验：&nbsp;&nbsp;<br />
<br />
<strong><span style="line-height: 21px"><span style="line-height: 26px; font-size: 18px">1、Like语句是否属于SARG取决于所使用的通配符的类型&nbsp;</span></span><br />
</strong><br />
如：name like &#8216;张%&#8217; ，这就属于SARG&nbsp;&nbsp;<br />
<br />
而：name like &#8216;%张&#8217; ,就不属于SARG。&nbsp;&nbsp;<br />
<br />
原因是通配符%在字符串的开通使得索引无法使用。&nbsp;&nbsp;<br />
<br />
<strong><span style="line-height: 21px"><span style="line-height: 26px; font-size: 18px">2、or 会引起全表扫描&nbsp;</span></span><br />
<br />
</strong>Name=&#8217;张三&#8217; and 价格&gt;5000 符号SARG，而：Name=&#8217;张三&#8217; or 价格&gt;5000 则不符合SARG。使用or会引起全表扫描。&nbsp;&nbsp;<br />
<br />
<strong><span style="line-height: 21px"><span style="line-height: 26px; font-size: 18px">3、非操作符、函数引起的不满足SARG形式的语句&nbsp;</span></span><br />
<br />
</strong>不满足SARG形式的语句最典型的情况就是包括非操作符的语句，如：NOT、!=、&lt;&gt;、!&lt;、!&gt;、NOT EXISTS、NOT IN、NOT LIKE等，另外还有函数。下面就是几个不满足SARG形式的例子：&nbsp;&nbsp;<br />
<br />
ABS(价格)&lt;5000&nbsp;&nbsp;<br />
<br />
Name like &#8216;%三&#8217;&nbsp;&nbsp;<br />
<br />
有些表达式，如：&nbsp;&nbsp;<br />
<br />
WHERE 价格*2&gt;5000&nbsp;&nbsp;<br />
<br />
SQL SERVER也会认为是SARG，SQL SERVER会将此式转化为：&nbsp;&nbsp;<br />
<br />
WHERE 价格&gt;2500/2&nbsp;&nbsp;<br />
<br />
但我们不推荐这样使用，因为有时SQL SERVER不能保证这种转化与原始表达式是完全等价的。&nbsp;&nbsp;<br />
<br />
<strong><span style="line-height: 21px"><span style="line-height: 26px; font-size: 18px">4、IN 的作用相当与OR&nbsp;</span></span><br />
</strong><br />
语句：&nbsp;&nbsp;<br />
<br />
Select * from table1 where tid in (2,3)&nbsp;&nbsp;<br />
<br />
和&nbsp;&nbsp;<br />
<br />
Select * from table1 where tid=2 or tid=3&nbsp;&nbsp;<br />
<br />
是一样的，都会引起全表扫描，如果tid上有索引，其索引也会失效。&nbsp;&nbsp;<br />
<br />
<strong><span style="line-height: 21px"><span style="line-height: 26px; font-size: 18px">5、尽量少用NOT&nbsp;</span></span><br />
<br />
<span style="line-height: 21px"><span style="line-height: 26px; font-size: 18px">6、exists 和 in 的执行效率是一样的&nbsp;</span></span><br />
</strong><br />
很多资料上都显示说，exists要比in的执行效率要高，同时应尽可能的用not exists来代替not in。但事实上，我试验了一下，发现二者无论是前面带不带not，二者之间的执行效率都是一样的。因为涉及子查询，我们试验这次用SQL SERVER自带的pubs数据库。运行前我们可以把SQL SERVER的statistics I/O状态打开。&nbsp;&nbsp;<br />
<br />
（1）select title,price from titles where title_id in (select title_id from sales where qty&gt;30)&nbsp;&nbsp;<br />
<br />
该句的执行结果为：&nbsp;&nbsp;<br />
<br />
表 'sales'。扫描计数 18，逻辑读 56 次，物理读 0 次，预读 0 次。&nbsp;&nbsp;<br />
<br />
表 'titles'。扫描计数 1，逻辑读 2 次，物理读 0 次，预读 0 次。&nbsp;&nbsp;<br />
<br />
（2）select title,price from titles where exists (select * from sales where sales.title_id=titles.title_id and qty&gt;30)&nbsp;&nbsp;<br />
<br />
第二句的执行结果为：&nbsp;&nbsp;<br />
<br />
表 'sales'。扫描计数 18，逻辑读 56 次，物理读 0 次，预读 0 次。&nbsp;&nbsp;<br />
<br />
表 'titles'。扫描计数 1，逻辑读 2 次，物理读 0 次，预读 0 次。&nbsp;&nbsp;<br />
<br />
我们从此可以看到用exists和用in的执行效率是一样的。&nbsp;&nbsp;<br />
<br />
<strong><span style="line-height: 21px"><span style="line-height: 26px; font-size: 18px">7、用函数charindex()和前面加通配符%的LIKE执行效率一样&nbsp;</span></span><br />
</strong><br />
前面，我们谈到，如果在LIKE前面加上通配符%，那么将会引起全表扫描，所以其执行效率是低下的。但有的资料介绍说，用函数charindex()来代替LIKE速度会有大的提升，经我试验，发现这种说明也是错误的：&nbsp;&nbsp;<br />
<br />
select gid,title,fariqi,reader from tgongwen where charindex('刑侦支队',reader)&gt;0 and fariqi&gt;'2004-5-5'&nbsp;&nbsp;<br />
<br />
用时：7秒，另外：扫描计数 4，逻辑读 7155 次，物理读 0 次，预读 0 次。&nbsp;&nbsp;<br />
<br />
select gid,title,fariqi,reader from tgongwen where reader like '%' + '刑侦支队' + '%' and fariqi&gt;'2004-5-5'&nbsp;&nbsp;<br />
<br />
用时：7秒，另外：扫描计数 4，逻辑读 7155 次，物理读 0 次，预读 0 次。&nbsp;&nbsp;<br />
<br />
<strong><span style="line-height: 21px"><span style="line-height: 26px; font-size: 18px">8、union并不绝对比or的执行效率高&nbsp;</span></span><br />
</strong><br />
我们前面已经谈到了在where子句中使用or会引起全表扫描，一般的，我所见过的资料都是推荐这里用union来代替or。事实证明，这种说法对于大部分都是适用的。&nbsp;&nbsp;<br />
<br />
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-16' or gid&gt;9990000&nbsp;&nbsp;<br />
<br />
用时：68秒。扫描计数 1，逻辑读 404008 次，物理读 283 次，预读 392163 次。&nbsp;&nbsp;<br />
<br />
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-16'&nbsp;&nbsp;<br />
<br />
union&nbsp;&nbsp;<br />
<br />
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid&gt;9990000&nbsp;&nbsp;<br />
<br />
用时：9秒。扫描计数 8，逻辑读 67489 次，物理读 216 次，预读 7499 次。&nbsp;&nbsp;<br />
<br />
看来，用union在通常情况下比用or的效率要高的多。&nbsp;&nbsp;<br />
<br />
但经过试验，笔者发现如果or两边的查询列是一样的话，那么用union则反倒和用or的执行速度差很多，虽然这里union扫描的是索引，而or扫描的是全表。&nbsp;&nbsp;<br />
<br />
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-16' or fariqi='2004-2-5'&nbsp;&nbsp;<br />
<br />
用时：6423毫秒。扫描计数 2，逻辑读 14726 次，物理读 1 次，预读 7176 次。&nbsp;&nbsp;<br />
<br />
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-16'&nbsp;&nbsp;<br />
<br />
union&nbsp;&nbsp;<br />
<br />
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-2-5'&nbsp;&nbsp;<br />
<br />
用时：11640毫秒。扫描计数 8，逻辑读 14806 次，物理读 108 次，预读 1144 次。&nbsp;&nbsp;<br />
<br />
<strong><span style="line-height: 21px"><span style="line-height: 26px; font-size: 18px">9、字段提取要按照&#8220;需多少、提多少&#8221;的原则，避免&#8220;select *&#8221;&nbsp;</span></span><br />
<br />
</strong>我们来做一个试验：&nbsp;&nbsp;<br />
<br />
select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc&nbsp;&nbsp;<br />
<br />
用时：4673毫秒&nbsp;&nbsp;<br />
<br />
select top 10000 gid,fariqi,title from tgongwen order by gid desc&nbsp;&nbsp;<br />
<br />
用时：1376毫秒&nbsp;&nbsp;<br />
<br />
select top 10000 gid,fariqi from tgongwen order by gid desc&nbsp;&nbsp;<br />
<br />
用时：80毫秒&nbsp;&nbsp;<br />
<br />
由此看来，我们每少提取一个字段，数据的提取速度就会有相应的提升。提升的速度还要看您舍弃的字段的大小来判断。&nbsp;&nbsp;<br />
<br />
<strong><span style="line-height: 21px"><span style="line-height: 26px; font-size: 18px">10、count(*)不比count(字段)慢&nbsp;</span></span><br />
</strong><br />
某些资料上说：用*会统计所有列，显然要比一个世界的列名效率低。这种说法其实是没有根据的。我们来看：&nbsp;&nbsp;<br />
<br />
select count(*) from Tgongwen&nbsp;&nbsp;<br />
<br />
用时：1500毫秒&nbsp;&nbsp;<br />
<br />
select count(gid) from Tgongwen&nbsp;&nbsp;<br />
<br />
用时：1483毫秒&nbsp;&nbsp;<br />
<br />
select count(fariqi) from Tgongwen&nbsp;&nbsp;<br />
<br />
用时：3140毫秒&nbsp;&nbsp;<br />
<br />
select count(title) from Tgongwen&nbsp;&nbsp;<br />
<br />
用时：52050毫秒&nbsp;&nbsp;<br />
<br />
从以上可以看出，如果用count(*)和用count(主键)的速度是相当的，而count(*)却比其他任何除主键以外的字段汇总速度要快，而且字段越长，汇总的速度就越慢。我想，如果用count(*)， SQL SERVER可能会自动查找最小字段来汇总的。当然，如果您直接写count(主键)将会来的更直接些。&nbsp;&nbsp;<br />
<br />
<strong><span style="line-height: 21px"><span style="line-height: 26px; font-size: 18px">11、order by按聚集索引列排序效率最高&nbsp;</span></span><br />
</strong><br />
我们来看：（gid是主键，fariqi是聚合索引列）&nbsp;&nbsp;<br />
<br />
select top 10000 gid,fariqi,reader,title from tgongwen&nbsp;&nbsp;<br />
<br />
用时：196 毫秒。 扫描计数 1，逻辑读 289 次，物理读 1 次，预读 1527 次。&nbsp;&nbsp;<br />
<br />
select top 10000 gid,fariqi,reader,title from tgongwen order by gid asc&nbsp;&nbsp;<br />
<br />
用时：4720毫秒。 扫描计数 1，逻辑读 41956 次，物理读 0 次，预读 1287 次。&nbsp;&nbsp;<br />
<br />
select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc&nbsp;&nbsp;<br />
<br />
用时：4736毫秒。 扫描计数 1，逻辑读 55350 次，物理读 10 次，预读 775 次。&nbsp;&nbsp;<br />
<br />
select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi asc&nbsp;&nbsp;<br />
<br />
用时：173毫秒。 扫描计数 1，逻辑读 290 次，物理读 0 次，预读 0 次。&nbsp;&nbsp;<br />
<br />
select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi desc&nbsp;&nbsp;<br />
<br />
用时：156毫秒。 扫描计数 1，逻辑读 289 次，物理读 0 次，预读 0 次。&nbsp;&nbsp;<br />
<br />
从以上我们可以看出，不排序的速度以及逻辑读次数都是和&#8220;order by 聚集索引列&#8221; 的速度是相当的，但这些都比&#8220;order by 非聚集索引列&#8221;的查询速度是快得多的。&nbsp;&nbsp;<br />
<br />
同时，按照某个字段进行排序的时候，无论是正序还是倒序，速度是基本相当的。&nbsp;&nbsp;<br />
<br />
<strong><span style="line-height: 21px"><span style="line-height: 26px; font-size: 18px">12、高效的TOP&nbsp;</span></span><br />
</strong><br />
事实上，在查询和提取超大容量的数据集时，影响数据库响应时间的最大因素不是数据查找，而是物理的I/0操作。如：&nbsp;&nbsp;<br />
<br />
select top 10 * from (&nbsp;&nbsp;<br />
<br />
select top 10000 gid,fariqi,title from tgongwen&nbsp;&nbsp;<br />
<br />
where neibuyonghu='办公室'&nbsp;&nbsp;<br />
<br />
order by gid desc) as a&nbsp;&nbsp;<br />
<br />
order by gid asc&nbsp;&nbsp;<br />
<br />
这条语句，从理论上讲，整条语句的执行时间应该比子句的执行时间长，但事实相反。因为，子句执行后返回的是10000条记录，而整条语句仅返回10条语句，所以影响数据库响应时间最大的因素是物理I/O操作。而限制物理I/O操作此处的最有效方法之一就是使用TOP关键词了。TOP关键词是SQL SERVER中经过系统优化过的一个用来提取前几条或前几个百分比数据的词。经笔者在实践中的应用，发现TOP确实很好用，效率也很高。但这个词在另外一个大型数据库ORACLE中却没有，这不能说不是一个遗憾，虽然在ORACLE中可以用其他方法（如：rownumber）来解决。在以后的关于&#8220;实现千万级数据的分页显示存储过程&#8221;的讨论中，我们就将用到TOP这个关键词。</div>
</div><img src ="http://www.cppblog.com/tx7do/aggbug/196222.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-12-13 19:00 <a href="http://www.cppblog.com/tx7do/archive/2012/12/13/196222.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>微软代码签名证书使用指南</title><link>http://www.cppblog.com/tx7do/archive/2012/12/06/196026.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Wed, 05 Dec 2012 16:04:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/12/06/196026.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/196026.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/12/06/196026.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/196026.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/196026.html</trackback:ping><description><![CDATA[<div><strong style="color: red">转载自：</strong><a style="color: red" href="http://www.willrey.com/support/signcode_guide_pfx.html"><strong>http://www.willrey.com/support/signcode_guide_pfx.html</strong></a><br /><br />
<p style="padding-bottom: 0px; widows: 2; text-transform: none; text-indent: 0px; margin: 10px 34px 0px 0px; padding-left: 0px; padding-right: 0px; font: 12px/18px Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(86,87,89); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">微软的代码签名软件 SignCode.exe 的缺省的&#8220;典型&#8221;签名类型，就是&#8220;从存储区选择&#8221;签名证书，同时由于微软的 Office 宏代码签名只支持同时包含了私钥和公钥的 PFX 格式签名证书，也就是直接&#8220;从存储区选择&#8221;签名证书。在收到证书后请用户先 Windows 的证书存储区导出备份签名证书，导出的证书格式为 PFX 格式，保管好证书的密码。<br /><br />下载Thawte代码签名证书的中级根证书：<br /><a style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(86,87,89); text-decoration: underline; padding-top: 0px" href="https://search.thawte.com/support/ssl-digital-certificates/index?page=content&amp;id=AR1382" target="_blank">https://search.thawte.com/support/ssl-digital-certificates/index?page=content&amp;id=AR1382</a></p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; text-indent: 0px; margin: 10px 34px 0px 0px; padding-left: 0px; padding-right: 0px; font: 12px/18px Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(86,87,89); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">下载VeriSign代码签名证书的中级根证书：<br /><a style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(86,87,89); text-decoration: underline; padding-top: 0px" href="http://www.verisign.com/support/verisign-intermediate-ca/code-signing-intermediate/index.html" target="_blank">http://www.verisign.com/support/verisign-intermediate-ca/code-signing-intermediate/index.html</a></p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; text-indent: 0px; margin: 10px 34px 0px 0px; padding-left: 0px; padding-right: 0px; font: 12px/18px Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(86,87,89); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><br />&nbsp;使用微软的<span class="Apple-converted-space">&nbsp;</span><strong style="color: rgb(86,87,89); font-size: 12px">SignCode.exe</strong><span class="Apple-converted-space">&nbsp;</span>就可以对微软的代码进行签名，如果您没有此文件，您可以点击<span class="Apple-converted-space">&nbsp;</span><a style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(86,87,89); text-decoration: underline; padding-top: 0px" href="http://www.willrey.com/support/signcode.exe">这里</a>下载。 Signcode.exe 可以使用 DOS 命令行方式实现签名，我们推荐用户使用数字签名向导方式，简单方便。请注意：如果您开发的ActiveX为IE加载项，请先数字签名每个CAB文件中的.dll和.ocx等文件，再把这些文件打包成.cab文件后再数字签名.cab文件，以确保所有IE加载项都被IE验证和信任，否则会显示&#8220;未验证&#8221;而可能影响正常运行。<br /><br />具体签名向导过程如下：</p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; text-indent: 0px; margin: 10px 34px 0px 0px; padding-left: 0px; padding-right: 0px; font: 12px/18px Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(86,87,89); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp;&nbsp;(1) 运行 Signcode.exe ，要求您选择需要签名的文件，支持：可执行文件 (*.exe; *.dll; *.ocx) ； Cabinet 打包文件 (*.cab) 和目录文件 (*.cat) ，如下图 1 所示 ( 如： TestSign.cab) ，请注意：如果签名的文件已经有数字签名，则会被新的签名覆盖<span class="Apple-converted-space">&nbsp;</span><img style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" alt="signcode" src="http://www.willrey.com/support/images/Signcode-01.JPG" width="500" height="380" /><br />(2) 点击&#8220;下一步&#8221;后，如下图 2 所示，会要求您选择&#8220;签名类型&#8221;， 直接点击&#8220;下一步&#8221;即可，即选择缺省的&#8220;典型&#8221;签名类型：<span class="Apple-converted-space">&nbsp;</span><br /><img style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" alt="signcode" src="http://www.willrey.com/support/images/Signcode-02.JPG" width="506" height="379" /><br />&nbsp;&nbsp;(3) 如下图 3 所示，点击&#8220;从存储区选择&#8221;，则会显示您的电脑证书存储区的所有证书，包括存储在电脑和 USB Key 中的所有数字证书，选择您的签名证书即可：<span class="Apple-converted-space">&nbsp;</span><br /><img style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" alt="verisign微软代码签名证书" src="http://www.willrey.com/support/images/Signcode-03.JPG" width="503" height="380" /><br />(4) 如下图 4 所示，要求填写该签名代码的功能描述，推荐一定要认真填写，因为此信息将会在最终用户下载此代码时显示，有助于最终用户了解此代码的功能以确定是否下载安装。第一行&#8220;描述&#8221;是指此代码的功能文字描述，第二行&#8220; Web 位置&#8221;则让最终用户点击文字描述来详细了解此代码的功能和使用方法等。</p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; text-indent: 0px; margin: 10px 34px 0px 0px; padding-left: 0px; padding-right: 0px; font: 12px/18px Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(86,87,89); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><img style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" alt="" src="http://www.willrey.com/support/images/Signcode-04.jpg" width="501" height="379" /><br />(5) 点击&#8220;下一步&#8221;后，如下图 9 所示，选中&#8220;将时间戳添加到数据中&#8221;，请使用:</p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; text-indent: 0px; margin: 10px 34px 0px 0px; padding-left: 0px; padding-right: 0px; font: 12px/18px Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(86,87,89); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">VeriSign 免费提供的时间戳URL：<strong style="color: rgb(86,87,89); font-size: 12px">http://timestamp.verisign.com/scripts/timestamp.dll</strong></p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; text-indent: 0px; margin: 10px 34px 0px 0px; padding-left: 0px; padding-right: 0px; font: 12px/18px Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(86,87,89); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp;&nbsp;时间戳服务非常重要，添加时间戳后，即使您的代码签名证书已经过期，但由于您的代码是在证书有效期内签名的，则时间戳服务保证了此代码仍然可信，最终用户仍然可以放心下载，使得即使代码签名证书已经过期，您也无需重签已经签名的代码。</p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; text-indent: 0px; margin: 10px 34px 0px 0px; padding-left: 0px; padding-right: 0px; font: 12px/18px Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(86,87,89); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><img style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" alt="" src="http://www.willrey.com/support/images/Signcode-05.jpg" width="501" height="378" /><br />&nbsp;(6) 点击&#8220;下一步&#8221;后，如下图 6 所示，会提示已经完成数字签名向导，点击&#8220;完成&#8221;就完成了中文版代码签名证书的代码签名。<br /><img style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" alt="" src="http://www.willrey.com/support/images/Signcode-06.jpg" width="504" height="379" /><span class="Apple-converted-space">&nbsp;</span><br /></p></div><img src ="http://www.cppblog.com/tx7do/aggbug/196026.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-12-06 00:04 <a href="http://www.cppblog.com/tx7do/archive/2012/12/06/196026.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Opus 音频编码正式标准化</title><link>http://www.cppblog.com/tx7do/archive/2012/11/27/195746.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Tue, 27 Nov 2012 13:26:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/27/195746.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195746.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/27/195746.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195746.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195746.html</trackback:ping><description><![CDATA[<div><strong style="color: red">转载自:</strong><a style="color: red" href="http://linuxtoy.org/archives/opus-accepted-as-a-new-standard-audio-codec.html"><strong>http://linuxtoy.org/archives/opus-accepted-as-a-new-standard-audio-codec.html</strong></a><br /><br />
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 14px/19px tahoma, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">先前提到过在<span class="Apple-converted-space">&nbsp;</span><a style="color: rgb(187,85,0); text-decoration: none" href="http://linuxtoy.org/archives/firefox-15-beta.html">Firefox 15 中引入的 Opus 音频编码</a>被正式接纳为新的国际互联网音频标准。<span id="more-6247"></span></p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 14px/19px tahoma, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Opus 由 Mozilla 和 Xiph.org 主导开发，得到了 Skype 和 Broadcom 的帮助。它完美融合了 Skype 的 SILK 低比特率语音编码和 Xiph.org 的 CELT 的高比特率低延迟音乐编码技术，实现了一种压缩音频编码覆盖从语音通话到高质量音乐流的目标。且看下图</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 14px/19px tahoma, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><a style="color: rgb(187,85,0); text-decoration: none" href="http://lt-file.b0.upaiyun.com/files/2012/09/opus-quality.png"><img style="border-bottom: rgb(187,187,187) 1px solid; border-left: rgb(187,187,187) 1px solid; padding-bottom: 3px; padding-left: 3px; padding-right: 3px; font: italic 11px tahoma, sans-serif; max-width: 100%; color: rgb(0,119,0); border-top: rgb(187,187,187) 1px solid; border-right: rgb(187,187,187) 1px solid; padding-top: 3px; border-image: initial" class="alignnone size-full wp-image-6248" title="opus-quality" alt="" src="http://lt-file.b0.upaiyun.com/files/2012/09/opus-quality.png" width="768" height="568" /></a></p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 14px/19px tahoma, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">音质方面，在<strong>低比特率状态下继承了 SILK 的优秀表现，在高比特率下听音测试表明也胜过 HE-AAC，且具有低延迟的特性</strong>。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 14px/19px tahoma, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Opus 可以封装到现有的 Ogg 容器中，通过指定<span class="Apple-converted-space">&nbsp;</span><code style="font-family: monospace; color: rgb(255,0,51)">codec</code><span class="Apple-converted-space">&nbsp;</span>来和 vorbis 编码的音频区分，推荐使用扩展名<span class="Apple-converted-space">&nbsp;</span><code style="font-family: monospace; color: rgb(255,0,51)">.opus</code><span class="Apple-converted-space">&nbsp;</span>。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 14px/19px tahoma, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><strong>此外最重要的是 Opus 将被作为 WebRTC 的一部分应用在未来的网络视频聊天中。</strong></p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 14px/19px tahoma, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">目前<span class="Apple-converted-space">&nbsp;</span><a style="color: rgb(187,85,0); text-decoration: none" href="http://gstreamer.freedesktop.org/news/#2012-02-21T14:00:00Z">GStreamer Bad Plugins 0.10.23</a><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><a style="color: rgb(187,85,0); text-decoration: none" href="http://trac.videolan.org/vlc/ticket/7185">VLC 2.0.4</a><span class="Apple-converted-space">&nbsp;</span>已经提供了对该音频编码的支持。<a style="color: rgb(187,85,0); text-decoration: none" href="https://apps.fedoraproject.org/packages/opus">Fedora</a><span class="Apple-converted-space">&nbsp;</span>及<span class="Apple-converted-space">&nbsp;</span><a style="color: rgb(187,85,0); text-decoration: none" href="https://apps.ubuntu.com/cat/applications/libopus0/">Ubuntu</a><span class="Apple-converted-space">&nbsp;</span>仓库中也已经打包了相关的编码包和开发工具。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 14px/19px tahoma, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><a style="color: rgb(187,85,0); text-decoration: none" href="http://en.wikipedia.org/wiki/Opus_(audio_format)">Opus 英文维基百科</a></p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 14px/19px tahoma, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><a style="color: rgb(187,85,0); text-decoration: none" href="http://www.opus-codec.org/">Opus 官方站点</a></p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 14px/19px tahoma, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><em>消息来源：</em><a style="color: rgb(187,85,0); text-decoration: none" href="http://arstechnica.com/gadgets/2012/09/newly-standardized-opus-audio-codec-fills-every-role-from-online-chat-to-music/">Ars Technia</a></p></div><img src ="http://www.cppblog.com/tx7do/aggbug/195746.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-27 21:26 <a href="http://www.cppblog.com/tx7do/archive/2012/11/27/195746.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>音频比特率</title><link>http://www.cppblog.com/tx7do/archive/2012/11/27/195743.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Tue, 27 Nov 2012 11:47:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/27/195743.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195743.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/27/195743.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195743.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195743.html</trackback:ping><description><![CDATA[<p><strong>CBR（Constant Bit Rate，固定比特率） <br />VBR（Variable Bit Rate，可变比特率） <br />ABR（Average Bit Rate，平均比特率） </strong></p>
<p>&nbsp;</p>
<p><strong>MP3（CBR、VBR、ABR）<br /><br /><br /></strong></p>
<p>　　<strong>CBR（Constant Bit Rate，固定比特率）</strong> </p>
<p>　　CBR是最古老最简单的MP3编码（压缩）方式。采用此法编码时，整个文件的比特率都是一样的，换言之，MP3文件每秒使用的比特率都是一样。尽管音乐文件有复杂程度不同的段落，编码器始终把比特率保持一致，除非你用最高音质，否则，MP3文件中不同段落的音质会有变化。越是复杂的段落，其音质就越差。它的最大优点是文件的尺寸固定，便于计算存储的空间。<br /><br /></p>
<p>　　<strong>VBR（Variable Bit Rate，可变比特率）</strong> </p>
<p>　　VBR是一种可变编码速率的MP3压缩方式，其原理就是将一首歌的复杂部分用高比特率编码，简单部分用低比特率编码，通过这种动态调整编码速率的方式，进一步得到音质和文件体积之间的平衡。它的主要优点是可以让整首歌都能大致达到我们的音质要求，缺点是编码时无法估计压缩出来的文件体积大小。 <br />现在推出的MP3随身听大部分都支持VBR了，不过有些机器虽然能够播放VBR格式的歌曲，但是不能够正确显示播放时间，目前许多高品质的MP3音乐都是采用VBR编码的。</p>
<p><br />　　<strong>ABR（Average Bit Rate，平均比特率）</strong> </p>
<p>　　ABR是VBR的一种插值参数，它是在VBR的基础上发展出来的一种编码方式，是针对CBR较大的文件体积和VBR生成文件体积大小不定的特点创造了这种编码模式。ABR在指定的文件大小内，以每50帧（30帧约1秒）为一段，低频和不敏感频率使用相对低的流量，高频和大动态表现时使用高流量，可以作为VBR和CBR的一种折中选择.</p><img src ="http://www.cppblog.com/tx7do/aggbug/195743.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-27 19:47 <a href="http://www.cppblog.com/tx7do/archive/2012/11/27/195743.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>speex 的一个例子, 使用了SPEEX抖动缓存. </title><link>http://www.cppblog.com/tx7do/archive/2012/11/23/195607.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Fri, 23 Nov 2012 08:56:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/23/195607.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195607.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/23/195607.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195607.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195607.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转载自:http://blog.163.com/yuan_zhch/blog/static/193790046201172743047588/http://svn.xiph.org/trunk/speex/speexclient/Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHigh...&nbsp;&nbsp;<a href='http://www.cppblog.com/tx7do/archive/2012/11/23/195607.html'>阅读全文</a><img src ="http://www.cppblog.com/tx7do/aggbug/195607.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-23 16:56 <a href="http://www.cppblog.com/tx7do/archive/2012/11/23/195607.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入剖析 iLBC 编码器原理</title><link>http://www.cppblog.com/tx7do/archive/2012/11/23/195599.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Fri, 23 Nov 2012 04:00:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/23/195599.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195599.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/23/195599.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195599.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195599.html</trackback:ping><description><![CDATA[<div>转载自:<a href="http://blog.csdn.net/wanggp_2007/article/details/5114309">http://blog.csdn.net/wanggp_2007/article/details/5114309</a><br /><br />
<div style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 20px 0px 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" id="article_content" class="article_content">
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 早在2005年就听说iLBC编解码算法，主要是应用在VOIP 的speech codec，但是一直没有深入研究算法原理，碰巧近期有一些时间可以学习一下它相比基于CELP模型的speech codec的优势。这套代码是浮点的，听朋友说要是转成定点代码会比较有用，只是可能需要的时间会多一点。如果想了解iLBC的一般介绍，如编码速率、应用等，可以参考前面的文章《<a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/wanggp_2007/article/details/wanggp_2007/archive/2009/12/25/5073048.aspx">iLBC编解码相关知识》<span class="Apple-converted-space">&nbsp;</span></a>，下面主要是我的一些学习笔记，仅供大家参考。</p>
<p>&nbsp;</p>
<p>&nbsp;一、算法整体流程</p>
<p>&nbsp;</p>
<p><img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/wanggp_2007/EntryImages/20091231/Picture1.png" width="603" height="301" /></p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 输入的语音逐帧进行预处理，然后计算LPC系数和残差信号，在残差信号中选择初始状态，并对其进行标量量化，再对剩下的残差信号进行增益/形状矢量量化，最后封包成比特流。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iLBC的每frame/block保持独立编码，这样才能保证在丢包的情况下，保持良好的重建语音质量；而CELP模型的codec往往都需要look head buffer 才能对当前帧进行编码，这样虽然可以使重建语音连接比较平滑，但是在网络传输中一旦发生丢包，则连续性遭到破坏，解码语音的质量就会下降。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在iLBC的编码流程中有三个模块Select Start state、Scalar quantization和CB Search是与CELP模型不同的，下面重点研究这三个模块。</p>
<p>1、起始状态（Start State）</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 这个概念是iLBC所特有的处理方式，下面以30ms frame mode为例，那么每个frame有6个sub-frame。iLBC在计算完LPC残差信号后，会找出整个帧内具有最高功率的两个连续子帧，来决定起始状态的位置。下图给出了start state 在两个子帧的位置。</p>
<p>&nbsp;<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/wanggp_2007/EntryImages/20091231/Picture2.png" width="513" height="493" /></p>
<p>&nbsp;</p>
<p>2、对起始状态样点的量化</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这里并不对两个子帧的全部sample进行精细量化，只是对从起始状态位置以后的57/58 sample（20ms/30ms frame mode）进行精细量化，所以这57/58 sample的量化需要三个部分：</p>
<p>1）子帧位置；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;是指哪两个子帧，如 sub-frame 0,1; 1,2; 2,3; 3,4; 4,5</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 3bit 量化这五种情况。</p>
<p>2）两个子帧内的前半部分还是后半部分；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 1bit 表示 state_first；</p>
<p>3）57/58 sample的标量量化。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这里首先要进行全通滤波，使得样点大小比较平均分布，然后进行能量的归一化，这个scaler factor用6bit标量量化，归一化后的样点动态范围就比较小了，然后对每一个样点都采用3bit 的DPCM量化。</p>
<p>&nbsp;</p>
<p>3、码书搜索</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 这部分是指起始状态量化后，整个frame剩余的样点量化方法。这里主要采用了动态码书的量化方法，码书是由整个frame的样点通过线性组合（加权滤波）和已经量化样点的解码信号组成，具体的流程见图3。</p>
<p>&nbsp;</p>
<p>&nbsp;<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/wanggp_2007/EntryImages/20091231/Picture3.png" width="695" height="295" /></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 上图首先解码已经量化的Start state，然后构建codebook memory，结合目标矢量进行感知加权滤波，在Codebook内部搜索与目标矢量最接近的矢量，这里采用三阶段的增益/形状矢量量化的方法进行搜索量化，最后调整增益以补偿能量损失。这里主要的重点还是码书的组成、大小以及量化顺序、搜索过程。</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 例如，图4给出了一个30ms 帧的量化顺序，这里有6个子帧，假设Start state是在1、2子帧之间，并且位置在两个子帧后半部分，那么进行量化的顺序如下：</p>
<p>1）Q0：量化Start State；</p>
<p>2）Q1：两个子帧内除了start state的22/23个样点；</p>
<p>3）Q2，Q3，Q4：Start state的后面每个子帧；</p>
<p>4）Q5：Start state的前面每个子帧；</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/wanggp_2007/EntryImages/20091231/Picture4.png" width="743" height="362" /></p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 到这里可以知道，目标矢量包括两种长度不同的矢量（除了start state）：22/23个样点的矢量和40个样点的子帧矢量，下表给出了对于不同矢量的码书大小。&nbsp;</p>
<p>&nbsp;<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/wanggp_2007/EntryImages/20091231/Picture5.png" width="883" height="295" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; 下图具体给出了量化目标矢量时动态码书的构造，需要注意的有以下几点：</p>
<p>1）不同的目标矢量（22/23、子帧40）对应的码书大小不同，具体数据见参考资料；</p>
<p>2）量化Start State前向的矢量需要对码书进行反转，再进行搜索，如对Q1、Q5进行量化；</p>
<p>3）动态码书的构成是解码的已量化样点而不是原来的经过感知加权的残差信号；</p>
<p>4）码书通过补零长度对齐；</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/wanggp_2007/EntryImages/20091231/Picture6.png" width="716" height="503" /></p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 增益/形状矢量量化属于乘积码矢量量化中的一种方法，它的基本思想就是将待量化的矢量的形状和增益分别量化，同时保持它们之间的有机联系，最后将码字相乘就可以得到重构矢量。这种量化方法可以实现高维数的矢量量化，以提高系统的性能。</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 下表给出了iLBC编码器的比特流定义，值得注意的是在封包前每个参数的bit是分成三个级别的，1表示最重要，2比较重要，3一般重要，因此封包是按照级别处理的，如图先处理级别1，然后级别2，最后级别3，这样提高了抗干扰性：&nbsp;<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/wanggp_2007/EntryImages/20091231/Picture7.png" width="747" height="400" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>二、总结</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 与传统的CELP模型的speech codec有较大不同，精髓在于帧内的独立编码，同时也利用了长时预测编码（LPC）去除冗余信息和语音信号本身准周期性的特征构造动态码书。与CELP模型codec相比，在丢包率较高的网络情况下，语音质量不会下降很快。对于解码端的丢包补偿算法（packet loss concealment）现在还没有看到，这个技术应该也是iLBC的一个特点。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>本文并没有列出详细的数据和语音质量评测，那些都可以在下面得参考资料找到。</p>
<p>&nbsp;</p>
<p>参考资料：</p>
<p>&nbsp;《rfc3951.txt》</p>
<p>&nbsp;</p>
<p>一家之言，欢迎讨论交流！</p></div><br class="Apple-interchange-newline" /></div><img src ="http://www.cppblog.com/tx7do/aggbug/195599.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-23 12:00 <a href="http://www.cppblog.com/tx7do/archive/2012/11/23/195599.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>speex开源项目的学习</title><link>http://www.cppblog.com/tx7do/archive/2012/11/23/195597.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Fri, 23 Nov 2012 03:37:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/23/195597.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195597.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/23/195597.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195597.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195597.html</trackback:ping><description><![CDATA[<div><strong style="color: red">转载自:</strong><a style="color: red" href="http://www.cnblogs.com/chef/archive/2012/07/20/2600846.html"><strong>http://www.cnblogs.com/chef/archive/2012/07/20/2600846.html</strong></a><br /><br />
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; 昨天讲了speex编译<a style="color: rgb(0,102,255); text-decoration: none" href="http://www.cnblogs.com/chef/archive/2012/07/19/2599067.html" target="_blank">http://www.cnblogs.com/chef/archive/2012/07/19/2599067.html</a>，今天又有空闲时间，简单分析一下项目中各工程的作用，以下为学习笔记。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; 项目是用C写的。solution中包含了以下10个project：</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">1.libspeex</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; speex动态库，核心project，用户使用的就是它，在solution中，接口头文件很贴心的放在了一个单独的文件夹中，名为Public Header Files。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">2.libspeexdsp</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; 静态库，从头文件名称可以看出，功能应该是回音抑制、抗抖动等专业算法，本以为它是由libspeex抽离出来的一个下层库，咱上层用户跟它是非耦合的。仔细看了看，发现它们并没有从属关系。后面看到的project 4依赖于1、2， &nbsp;7、8、9只依赖于1，说明2和1是平级的关系，2为1的补充，当需要使用speex的一些高级功能选项时，就需要使用到2了。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">3.speexdec</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; 示例exe，功能比较全的speex解码控制台程序，输入是格式为raw PCM或者WAVE文件，输出是speex编码文件，我尝试了一下，VLC可以播放。搜索到main函数，可以看到一堆控制台参数提示信息。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">4.speexenc</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; 同上，只是编码换成解码了。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">5.testdenoise</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; 测试libspeexdsp中的噪音消除功能。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">6.testecho</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; 测试libspeexdsp中的AEC即回音抑制功能。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">7.testenc</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; 测试窄带编码。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">8.testenc_uwb</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; 使用SPEEX_MODEID_UWB初始化编码。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">9.testenc_wb</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; 测试宽带编码。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">7、8、9的区别</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; speex三种主要的采样率8kHz、16kHz、32kHz，它们分别对应 narrowband、wideband、ultra-wideband（即7、9、8）。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp;&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">那么7、8、9和4有什么区别呢？</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; 其实它们都是很小的测试或示例程序，3可以通过控制台参数来控制编码选项（即上面所说的，使用了project 2）。个人感觉，看看9就可以动手写自己的代码了，日后需要用到一些选项时（应该是做优化工作）再去看manual手册+project 4。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">10.testresample</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; 这个工程有点搞，里面就一个名为testresample.c的文件，可是竟然不存在！这个工程依赖于libspeexdsp，个人感觉（我又开始猜了）应该是测试resample功能的。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">manual手册关于resamper的说明：</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; 在一些情况下，把音频从一种抽样率（sampling rate）转化成另一种是很有用的。比如说以下场景：混合不同抽样率的流，有的抽样率声卡不支持，转码等等。所以我们需要resampler。</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">后记：</p>
<p style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; margin: 10px auto; font: 13px/23px Verdana, Arial, sans-serif, 'Lucida Grande'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; &nbsp; speex项目中各工程作用就简单分析到这了，真要使用speex的话，看manual文档是必不可少的。日后如果有时间继续学习speex，我会把笔记分享上来的。</p></div><img src ="http://www.cppblog.com/tx7do/aggbug/195597.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-23 11:37 <a href="http://www.cppblog.com/tx7do/archive/2012/11/23/195597.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>directsound抓取麦克风PCM数据封装类 </title><link>http://www.cppblog.com/tx7do/archive/2012/11/23/195585.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 22 Nov 2012 16:11:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/23/195585.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195585.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/23/195585.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195585.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195585.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转载自:http://blog.chinaunix.net/uid-8272118-id-2033248.html网上有很多方法从麦克风读取PCM数据，不想一一举例。只是在这里发布一个我自己写的directsound的麦克风PCM数据采集类，通过它，可以很方便的利用directsound技术把麦克风的数据采集到，而且本身，开发者不必太在意自己会不会directsound编程，可以很方便的让开发...&nbsp;&nbsp;<a href='http://www.cppblog.com/tx7do/archive/2012/11/23/195585.html'>阅读全文</a><img src ="http://www.cppblog.com/tx7do/aggbug/195585.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-23 00:11 <a href="http://www.cppblog.com/tx7do/archive/2012/11/23/195585.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>丢包补偿技术调查</title><link>http://www.cppblog.com/tx7do/archive/2012/11/22/195584.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 22 Nov 2012 15:52:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/22/195584.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195584.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/22/195584.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195584.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195584.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转载自:http://silversand.blog.51cto.com/820613/166161摘要&nbsp;调查显示了用于IP网络语音应用的各种丢包补偿技术。丢包补偿技术可以分为两类：基于发送端补偿和基于接受端补偿。基于发送端补偿包括前向差错纠正、交织和重传技术；基于接受端补偿包括了多种错误隐蔽算法。最后给出了应用建议。&nbsp;一、基于发送端补偿基于发送端补偿可以分...&nbsp;&nbsp;<a href='http://www.cppblog.com/tx7do/archive/2012/11/22/195584.html'>阅读全文</a><img src ="http://www.cppblog.com/tx7do/aggbug/195584.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-22 23:52 <a href="http://www.cppblog.com/tx7do/archive/2012/11/22/195584.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解密回声消除技术之二（应用篇）</title><link>http://www.cppblog.com/tx7do/archive/2012/11/22/195582.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 22 Nov 2012 15:51:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/22/195582.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195582.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/22/195582.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195582.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195582.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转载自:http://silversand.blog.51cto.com/820613/166101(接《解密回声消除技术之一（理论篇）》)从应用平台来看，根据笔者多年的经验，可以把回声消除分为两大类：基于DSP等实时平台的回声消除技术和基于Windows等非实时平台的回声消除技术。两者的技术难度和重点是不一样的。&nbsp;三、基于DSP平台的回声消除技术回声消除技术传统...&nbsp;&nbsp;<a href='http://www.cppblog.com/tx7do/archive/2012/11/22/195582.html'>阅读全文</a><img src ="http://www.cppblog.com/tx7do/aggbug/195582.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-22 23:51 <a href="http://www.cppblog.com/tx7do/archive/2012/11/22/195582.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解密回声消除技术之一（理论篇）</title><link>http://www.cppblog.com/tx7do/archive/2012/11/22/195581.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 22 Nov 2012 15:49:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/22/195581.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195581.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/22/195581.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195581.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195581.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转载自:http://silversand.blog.51cto.com/820613/166095一、前言因为工作的关系，笔者从2004年开始接触回声消除(Echo Cancellation)技术，而后一直在某大型通讯企业从事与回声消除技术相关的工作，对回声消除这个看似神秘、高端和难以理解的技术领域可谓知之甚详。要了解回声消除技术的来龙去脉，不得不提及作为现代通讯技术的理论基础&...&nbsp;&nbsp;<a href='http://www.cppblog.com/tx7do/archive/2012/11/22/195581.html'>阅读全文</a><img src ="http://www.cppblog.com/tx7do/aggbug/195581.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-22 23:49 <a href="http://www.cppblog.com/tx7do/archive/2012/11/22/195581.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网页游戏分线到不分线</title><link>http://www.cppblog.com/tx7do/archive/2012/11/22/195532.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 22 Nov 2012 03:16:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/22/195532.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195532.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/22/195532.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195532.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195532.html</trackback:ping><description><![CDATA[<div><strong style="color: red">转载自：</strong><a style="color: red" href="http://www.cnblogs.com/me-sa/archive/2011/12/10/erlang0020.html"><strong>http://www.cnblogs.com/me-sa/archive/2011/12/10/erlang0020.html</strong></a><br /><br />
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp;&nbsp; 这一年来可以明显看到一个变化：网页游戏分线从标配逐渐变成了可选，越来越多的游戏开始不分线；当初为什么要分线？现在为什么又不分线？技术上面临着什么挑战？仅仅是技术问题么？</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><strong>术语解释</strong></p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp; 不同的技术实现"一条线"的概念也不尽相同，我们使用的Erlang实现，这里的一条线对应Erlang的一个VM.</p>
<h1 style="background-image: url(http://common.cnblogs.com/Skins/redcross/images/bg_title.gif); border-bottom: rgb(204,204,204) 0px dashed; text-align: left; line-height: 18px; widows: 2; text-transform: none; background-color: rgb(255,255,255); font-variant: normal; font-style: normal; text-indent: 0px; margin: 10px 0px; padding-left: 10px; letter-spacing: normal; font-family: Verdana, Helvetica, Arial; white-space: normal; orphans: 2; height: 23px; color: white; font-size: 12px; word-spacing: 0px; padding-top: 2px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">为什么要分线？</h1>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp;&nbsp; 可以通过比较来回答这个问题：所有玩家都在同一条线上 VS 同样数量的玩家被分配在多条线；如果所有玩家(假定1000人)都在一条线上首先同一场景的玩家数就会比较高，特别是一些游戏的热点区域比如副本入口，主城中心，传送门等等，当然同屏人数也会高；服务器端对应相关场景的广播压力，和业务逻辑的运算压力都集中在一条线上。而进行了分线之后，相当于把玩家做了分流，同一场景以及同屏的人数都会减少，一方面服务器端单条线的运算压力下降了，另一方面客户端的同屏人数也降了下来；</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp;分线实际上帮服务器端和客户端都减轻了压力，特别是很长一段时间内Flash客户端的同屏人数一直有人数限制，多数游戏能做到100多人，不会超过200人；这实际上是木桶理论中的短板，即使服务器端能做到不分线，客户端也支撑不了那么高的同屏；（当然现在这个问题已经有了突破）</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 总结一下，为什么分线：分担运算压力 同屏人数限制</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<h1 style="background-image: url(http://common.cnblogs.com/Skins/redcross/images/bg_title.gif); border-bottom: rgb(204,204,204) 0px dashed; text-align: left; line-height: 18px; widows: 2; text-transform: none; background-color: rgb(255,255,255); font-variant: normal; font-style: normal; text-indent: 0px; margin: 10px 0px; padding-left: 10px; letter-spacing: normal; font-family: Verdana, Helvetica, Arial; white-space: normal; orphans: 2; height: 23px; color: white; font-size: 12px; word-spacing: 0px; padding-top: 2px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">分线对设计的影响</h1>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp; 分线实际上是突破技术瓶颈支撑更多玩家的方案，一旦分线自然就会带来"换线"和"跨线"的问题；所谓换线，就是玩家显示的从一条线路切换到另一条线路；不在同一条线的玩家就属于"跨线"；玩家一个在1线，一个在2线，他们要交易怎么办？组队呢？聊天呢？战斗呢？即使是忽略掉交互的因素，只看一个玩家，这一个玩家上线应该选择哪条线？如果玩家在战斗，交易，挂机等状态下能够换线么？在这些状态下下线然后上线怎么处理？</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 本质上换线实际上是玩家数据从一个Erlang节点迁移到另一个Erlang节点，有一个销毁和重建的过程；而跨线是两个玩家的数据在不同的Erlang节点内。</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 一部分解决方案是来自于策划，会有一些游戏状态的互斥，比如不允许跨线交易，不允许在修炼状态换线，等等；另外一方面就要在做设计的时候充分考虑分线了：</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp; 玩家不在一条线怎么办？玩家当前能不能换线？玩家在当前这个状态换线了怎么办？玩家下线之后再上线怎么办？我这个服务是全局的应该怎么办？......</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp; 具体技术实现上，Erlang做这个有先天优势，启动多个节点，设计一个网关节点做负载均衡；做水平扩展是很容易的。</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<h1 style="background-image: url(http://common.cnblogs.com/Skins/redcross/images/bg_title.gif); border-bottom: rgb(204,204,204) 0px dashed; text-align: left; line-height: 18px; widows: 2; text-transform: none; background-color: rgb(255,255,255); font-variant: normal; font-style: normal; text-indent: 0px; margin: 10px 0px; padding-left: 10px; letter-spacing: normal; font-family: Verdana, Helvetica, Arial; white-space: normal; orphans: 2; height: 23px; color: white; font-size: 12px; word-spacing: 0px; padding-top: 2px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">分线血泪</h1>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 可以发现分线的设计需要在完成某一个功能的同时考虑到多条线的情况，会增加问题的复杂度；我不知道有多少采取分线策略的游戏曾经因为分线栽过跟头,我们就差点因为分线的一个bug把游戏经济系统搞死；事情大概经过：</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 某周日23点左右 运营的同事告诉我游戏内有玩家金币异常</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp;23:30左右到公司&nbsp; 封号，分析日志，发现金币来源应该是玩家交易，排除服务器被攻击可能</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 0点左右&nbsp; 封锁了交易的所有协议，停服更新</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 1点左右 发现还有一处可能出现问题的地方 再次更新</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 2点 从玩家日志库抓取异常玩家的数据做分析 发现玩家金币成倍增长2 4 8 16 32 64 也就是说，金币被&#8221;复制了&#8220;，但是玩家怎么做到的？是自己和自己交易么？分析代码虽然缺少这个防护，但是交易使用的SQL也保证了他得不到收益。</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 3:00 ~5:00 在本地测试环境，反复模拟各种情况下的交易，答案：当时游戏存在一个分线选择的bug导致玩家可以同时登陆两条线，玩家使用两个账号反复登陆换线，然后进行交易就可以把金币通过交易复制；&nbsp;&nbsp;</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp; 6点左右补丁做好热更新第一个版本</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp; 7点左右客户端补丁也做了分发</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 第二天运营提交了相关账号的修复规则，一个游戏的充值有一个前提保证就是游戏内的经济系统稳定，一旦出现刷金币之类的事情搞乱了经济系统，这个游戏服也就死掉了；</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<h1 style="background-image: url(http://common.cnblogs.com/Skins/redcross/images/bg_title.gif); border-bottom: rgb(204,204,204) 0px dashed; text-align: left; line-height: 18px; widows: 2; text-transform: none; background-color: rgb(255,255,255); font-variant: normal; font-style: normal; text-indent: 0px; margin: 10px 0px; padding-left: 10px; letter-spacing: normal; font-family: Verdana, Helvetica, Arial; white-space: normal; orphans: 2; height: 23px; color: white; font-size: 12px; word-spacing: 0px; padding-top: 2px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">为什么不分线了？</h1>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp; 首先分线的种种限制，比如跨线不能交易等等增加了玩家操作步骤，需要玩家先选择换线；另外，分线分流玩家分散了压力也分散了人气，显得游戏不热闹；</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp;&nbsp;其次在Flash同屏问题已经有了优化方案，可以看一下现在非常火爆的神魔遮天，它的同屏人数远远超出了100的限制；观察一下神魔遮天的处理，当一个区域聚集了很多人的时候，它并不是一下全部渲染出来，而是一个一个渲染出来的；还有一些客户端的优化策略，这些方案的组合结果就是同屏人数可以更多；</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<h1 style="background-image: url(http://common.cnblogs.com/Skins/redcross/images/bg_title.gif); border-bottom: rgb(204,204,204) 0px dashed; text-align: left; line-height: 18px; widows: 2; text-transform: none; background-color: rgb(255,255,255); font-variant: normal; font-style: normal; text-indent: 0px; margin: 10px 0px; padding-left: 10px; letter-spacing: normal; font-family: Verdana, Helvetica, Arial; white-space: normal; orphans: 2; height: 23px; color: white; font-size: 12px; word-spacing: 0px; padding-top: 2px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">怎么实现？</h1>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp; 有的不分线是通过拆分游戏的功能模块实现的，比如把场景运算放在单独的erlang节点，以功能为单位拆分成多个节点分担压力；一旦压力上去就可以通过增加对应的功能节点来缓解压力；实际上是换了一种分担压力的方式，对于客户端和玩家这些都是透明的。</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 我们从分线到不分线更困难一些，之前所有的逻辑都是在一个节点内完成，很难按照功能拆分游戏，那将是颠覆性的。咨询立涛，他给我们的建议是只开一条线，开启SMP，单线支撑2000~3000人应该没有问题。</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; Erlang SMP VM比普通Erlang VM要慢那么一点点，但是可以充分发挥多核优势&nbsp;摘录一点资料：</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 从OTP R12B开始，如果操作系统报告有多于1个的CPU（或者核心）VM的SMP版本会自动启动，并且根据CPU或者核心的数量启动同样数量的调度器。</p>
<p style="text-align: justify; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.5em; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp; 没有SMP支持的Erlang VM只有1个运行在主处理线程中的调度器。该调度器从运行队列（run-queue）中取出可以运行的Erlang进程以及IO任务，而且因为只有一个线程访问他们所以无须锁定任何数据。而带有SMP支持的Erlang VM可以有一个或多个调度器，每个运行在一个线程中。调度器从同一个公共运行队列中取出可运行的Erlang进程和IO任务。在SMP VM中所有的共享数据结构都会由锁进行保护，运行队列就是这样一个由锁保护的数据结构。</p>
<p style="text-align: justify; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.5em; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 详情看这里：<a style="color: gray; text-decoration: " href="http://shiningray.cn/some-facts-about-erlang-and-smp.html">http://shiningray.cn/some-facts-about-erlang-and-smp.html</a></p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 实践过程中，我们还是采取了一个折中的方案，只要玩家在一条线上不超过阈值，就只开启这一条线，客户端也没有线路选择的功能，如果超过阈值，就开启新线路，并通知客户端显示选线功能；</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<h1 style="background-image: url(http://common.cnblogs.com/Skins/redcross/images/bg_title.gif); border-bottom: rgb(204,204,204) 0px dashed; text-align: left; line-height: 18px; widows: 2; text-transform: none; background-color: rgb(255,255,255); font-variant: normal; font-style: normal; text-indent: 0px; margin: 10px 0px; padding-left: 10px; letter-spacing: normal; font-family: Verdana, Helvetica, Arial; white-space: normal; orphans: 2; height: 23px; color: white; font-size: 12px; word-spacing: 0px; padding-top: 2px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">仅仅是技术问题么？</h1>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp;从分线到不分线不仅仅是技术问题，策划同样要做调整，比如游戏内的一些容易堆积玩家的区域要想办法分散压力，比如增加入口，修改NPC位置等等；还有一些数值限制也需要重新考虑，比如一个活动分线模式最多只允许30个玩家参与，不分线了这个限制就要改掉否则大部分玩家都参与不了这个活动。</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 单服最高在线超过3000人怎么办？首先现在游戏平台能推到这个在线的情况都很少了；其次如果超过这个值，一般都是开启新服，也就是通过运营手段而非技术手段解决这个问题。</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 从分线到不分线，下一站是什么？一个世界？</p>
<p style="text-align: justify; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; letter-spacing: normal; font: 12px/18px Verdana, Helvetica, Arial; white-space: normal; orphans: 2; color: rgb(48,48,48); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 对于开发者，下一战又是什么？</p><br class="Apple-interchange-newline" /></div><img src ="http://www.cppblog.com/tx7do/aggbug/195532.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-22 11:16 <a href="http://www.cppblog.com/tx7do/archive/2012/11/22/195532.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>音频编解码-speex库的使用方法</title><link>http://www.cppblog.com/tx7do/archive/2012/11/22/195519.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Wed, 21 Nov 2012 17:27:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/22/195519.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195519.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/22/195519.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195519.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195519.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转载自:http://www.rosoo.net/a/201010/10363.htmlSpeex是近年来开发出的一套功能强大的语音引擎，能够实现高质量和低比特率的编码。它不仅提供了基于码激励线性预测（CELP）算法的编/解码模块， 而且在其最新发布的版本中还提供了声音预处理和声学回声消除模块，为保障IP网络中的语音通信质量提供了技术手段。此外，Speex还具有压缩后的比特率 低（2~44 k...&nbsp;&nbsp;<a href='http://www.cppblog.com/tx7do/archive/2012/11/22/195519.html'>阅读全文</a><img src ="http://www.cppblog.com/tx7do/aggbug/195519.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-22 01:27 <a href="http://www.cppblog.com/tx7do/archive/2012/11/22/195519.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>I帧、P帧和B帧的特点</title><link>http://www.cppblog.com/tx7do/archive/2012/11/22/195516.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Wed, 21 Nov 2012 16:29:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/22/195516.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195516.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/22/195516.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195516.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195516.html</trackback:ping><description><![CDATA[<div><strong style="color: red">转载自:</strong><a style="color: red" href="http://www.rosoo.net/a/201103/10995.html"><strong>http://www.rosoo.net/a/201103/10995.html</strong></a><br /><br /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">I帧:帧内编码帧</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">I帧特点:</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">1.它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">2.解码时仅用I帧的数据就可重构完整图像;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">3.I帧描述了图像背景和运动主体的详情;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">4.I帧不需要参考其他画面而生成;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">5.I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">6.I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">7.I帧不需要考虑运动矢量;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">8.I帧所占数据的信息量比较大。</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">P帧:前向预测编码帧。</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">P帧的预测与重构:P帧是以I帧为参考帧,在I帧中找出P帧&#8220;某点&#8221;的预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P帧&#8220;某点&#8221;的预测值并与差值相加以得到P帧&#8220;某点&#8221;样值,从而可得到完整的P帧。</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">P帧特点:</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">1.P帧是I帧后面相隔1~2帧的编码帧;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">2.P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">3.解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">4.P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">5.P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">6.由于P帧是参考帧,它可能造成解码错误的扩散;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">7.由于是差值传送,P帧的压缩比较高。</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">B帧:双向预测内插编码帧。</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">B帧的预测与重构</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">B帧以前面的I或P帧和后面的P帧为参考帧,&#8220;找出&#8221;B帧&#8220;某点&#8221;的预测值和两个运动矢量,并取预测差值和运动矢量传送。接收端根据运动矢量在两个参考帧中&#8220;找出(算出)&#8221;预测值并与差值求和,得到B帧&#8220;某点&#8221;样值,从而可得到完整的B帧。</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">B帧特点</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">1.B帧是由前面的I或P帧和后面的P帧来进行预测的;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">2.B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">3.B帧是双向预测编码帧;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">4.B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">5.B帧不是参考帧,不会造成解码错误的扩散。</span><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">注:I、B、P各帧是根据压缩算法的需要,是人为定义的,它们都是实实在在的物理帧,至于图像中的哪一帧是I帧,是随机的,一但确定了I帧,以后的各帧就严格按规定顺序排列。</span></div><img src ="http://www.cppblog.com/tx7do/aggbug/195516.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-22 00:29 <a href="http://www.cppblog.com/tx7do/archive/2012/11/22/195516.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>voip常用编码带宽计算</title><link>http://www.cppblog.com/tx7do/archive/2012/11/22/195515.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Wed, 21 Nov 2012 16:21:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/22/195515.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195515.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/22/195515.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195515.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195515.html</trackback:ping><description><![CDATA[<div><strong style="color: red">转载自:</strong><a style="color: red" href="http://www.rosoo.net/a/201105/12132.html"><strong>http://www.rosoo.net/a/201105/12132.html</strong></a><br /><br />
<p style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">voip常用编码带宽计算VOIP计算方法如下，和哪个厂家的没有什么关系：<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />带宽＝包长度&#215;每秒包数<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />＝包长度&#215;（1/打包周期）<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />＝（Ethernet头＋IP头＋UDP头＋RTP头＋有效载荷）&#215;（1/打包周期）<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />＝（208bit ＋160bit＋64bit＋96bit ＋有效载荷）&#215;（1/打包周期）<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />＝（528bit＋（打包周期(秒)&#215;每秒的比特数））&#215;（1/打包周期）<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />＝( 528 / 打包周期 ) ＋ 每秒比特数<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />按照上面的计算公式：<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />G711：20ms打包，带宽为 ( 528/20 + 64) Kbit/s＝<font style="padding-bottom: 0px; line-height: 1.3em; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" color="red" size="3" face="">90.4 Kbit/s</font></p>
<div style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font: 14px/25px Verdana, Arial, Tahoma; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" id="blogDetailDiv"><wbr style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />G729：20ms打包，带宽为 ( 528/20 + 8 ) Kbit/s＝<span class="Apple-converted-space">&nbsp;</span><font style="padding-bottom: 0px; line-height: 1.3em; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" size="3" face="">34.4 Kbit/s</font><wbr style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />G723：5.3k，30ms打包，带宽为 ( 528/30 + 5.3 ) Kbit/s＝<font style="padding-bottom: 0px; line-height: 1.3em; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" size="3" face="">22.9 Kbit/s</font><wbr style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />业界一般按照下表提供的IP网带宽系数和以太网带宽系数来设计网络带宽：<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />编解码技术&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;压缩速率（Kbps）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;打包周期（ms）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IP网带宽系数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以太网带宽系数<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />G.711 a/u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 64&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.41<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />G.729 a/b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.38&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.54<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />G.723.1(5.3kbit/s)&nbsp;&nbsp;5.3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.27&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.37<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />G.723.1(6.3Kbit/s)&nbsp;&nbsp;6.3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.36<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />H.263(384Kbit/s)&nbsp;&nbsp;&nbsp;&nbsp;&#8776;384&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6.2<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />注：采用某种编码方式时，用64K乘以相应的带宽系数就可以得出其实际占用的带宽。当然如果是中继接口，还需要考虑信令占据一定的带宽，一般按照2.5%来计算。</div></div><img src ="http://www.cppblog.com/tx7do/aggbug/195515.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-22 00:21 <a href="http://www.cppblog.com/tx7do/archive/2012/11/22/195515.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Speex手册----Speex编/解码API的使用(libspeex)</title><link>http://www.cppblog.com/tx7do/archive/2012/11/22/195513.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Wed, 21 Nov 2012 16:03:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/22/195513.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195513.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/22/195513.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195513.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195513.html</trackback:ping><description><![CDATA[<div><strong style="color: red">转载自:</strong><a style="color: red" href="http://blog.csdn.net/dotscylla/article/details/4426220"><strong>http://blog.csdn.net/dotscylla/article/details/4426220</strong></a>
<div style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 20px 0px 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" id="article_content">
<p><span style="font-size: small"><strong>前言：</strong>Speex官网：</span><a style="color: rgb(51,102,153); text-decoration: none" href="http://speex.org/"><span style="color: rgb(51,102,153)"><span style="font-size: small">http://speex.org/</span></span></a><span style="font-size: small">&nbsp;可以再Documentation下找到PDF版或HTML OL版的英文手册。可能会由于英文技能的匮乏或语音解码领域的不熟悉会有翻译错误，所以每段我都会付上英文原段落，也望各位发现后能够不吝赐教，大家共同进步。</span></p>
<p>&nbsp;</p>
<p><span style="font-size: small">PS: 1) 如需转载，注明出处，不胜感激; 2) 如侵您版权，及时通知，速删之</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/dotscylla/article/details/4426220#Decoding"></a></span></span></p>
<p><span style="font-family: 宋体"></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/dotscylla/article/details/4426220#Encoding">5.1 编码</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/dotscylla/article/details/4426220#Decoding">5.2 解码</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/dotscylla/article/details/4426220#CodecOption">5.3 编解码选项(speex_*_ctl)</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/dotscylla/article/details/4426220#ModeQuery">5.4 模式查询</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/dotscylla/article/details/4426220#Packing&amp;In-band Signalling">5.5 封包和带内信令</a></span></span></p><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/dotscylla/article/details/4426220#Packing&amp;In-band Signalling"></a>
<p>&nbsp;</p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/dotscylla/article/details/4426220#Markup"><span style="font-family: arial, helvetica, sans-serif">补充</span></a></span></span></p>
<p>&nbsp;</p><pre style="word-wrap: break-word; white-space: pre-wrap"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/dotscylla/article/details/4426220#PostScript">后记</a></span></pre>
<p>&nbsp;</p>
<p><span style="font-size: small">The libspeex library contains all the functions for encoding and decoding speech with the Speex codec. When linking on a UNIX system, one must add -lspeex -lm to the compiler command line. One important thing to know is that libspeex calls are reentrant, but not thread-safe. That means that it is fine to use calls from many threads, but calls using the same state from multiple threads must be protected by mutexes. Examples of code can also be found in Appendix A and the complete API documentation is included in the Documentation section of the Speex website (<a style="color: rgb(51,102,153); text-decoration: none" href="http://www.speex.org/">http://www.speex.org/</a>).</span></p>
<p style="text-indent: 21pt"><span style="font-size: small">Speex<span style="font-family: 宋体">编解码器的</span>libspeex<span style="font-family: 宋体">包囊括了所有的语音编码和解码函数。在</span>Linux<span style="font-family: 宋体">系统中连接时，必须在编译器命令行中加入</span>-lspeex &#8211;lm<span style="font-family: 宋体">。需要知道的是，虽然</span>libspeex<span style="font-family: 宋体">的函数调用是可重入的，但不是线程安全的，所以在多线程调用时，如果使用共享资源需要进行互斥保护。附录</span>A<span style="font-family: 宋体">中有代码实例，在</span>Speex<span style="font-family: 宋体">站点(</span><a style="color: rgb(51,102,153); text-decoration: none" href="http://www.speex.org/">http://www.speex.org/</a>&nbsp;)<span style="font-family: 宋体">的文档部分能下到完整的</span>API<span style="font-family: 宋体">文档。</span></span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2><a style="color: rgb(51,102,153); text-decoration: none" name="t0"></a><span style="font-family: Arial"><a style="color: rgb(51,102,153); text-decoration: none" name="Encoding"></a>5.1&nbsp;</span><span style="font-family: 黑体">编码</span></h2>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">In order to encode speech using Speex, one first needs to:<br />#include &lt;speex/speex.h&gt;<br />Then in the code, a Speex bit-packing struct must be declared, along with a Speex encoder state:<br />SpeexBits bits;</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">void *enc_state;<br />The two are initialized by:<br />speex_bits_init(&amp;bits);<br />enc_state = speex_encoder_init(&amp;speex_nb_mode);<br />For wideband coding, speex_nb_mode will be replaced by speex_wb_mode. In most cases, you will need to know the frame size used at the sampling rate you are using. You can get that value in the frame_size variable (expressed in samples, not<br />bytes) with:<br />speex_encoder_ctl(enc_state,SPEEX_GET_FRAME_SIZE,&amp;frame_size);<br />In practice, frame_size will correspond to 20 ms when using 8, 16, or 32 kHz sampling rate. There are many parameters that can be set for the Speex encoder, but the most useful one is the quality parameter that controls the quality vs bit-rate tradeoff.<br />This is set by:<br />speex_encoder_ctl(enc_state,SPEEX_SET_QUALITY,&amp;quality);<br />where quality is an integer value ranging from 0 to 10 (inclusively). The mapping between quality and bit-rate is described in Fig. 9.2 for narrowband.<br />Once the initialization is done, for every input frame:<br />speex_bits_reset(&amp;bits);<br />speex_encode_int(enc_state, input_frame, &amp;bits);<br />nbBytes = speex_bits_write(&amp;bits, byte_ptr, MAX_NB_BYTES);<br />where input_frame is a (short *) pointing to the beginning of a speech frame, byte_ptr is a (char *) where the encoded frame will be written,MAX_NB_BYTES is the maximumnumber of bytes that can be written to byte_ptr without causing an overflow and nbBytes is the number of bytes actually written to byte_ptr (the encoded size in bytes). Before calling speex_bits_write, it is possible to find the number of bytes that need to be written by calling speex_bits_nbytes(&amp;bits), which returns a number of bytes.<br />It is still possible to use the speex_encode() function, which takes a (float *) for the audio. However, this would make an eventual port to an FPU-less platform (like ARM) more complicated. Internally, speex_encode() and speex_encode_int() are processed in the same way. Whether the encoder uses the fixed-point version is only decided by the compile-time flags, not at the API level.<br />After you&#8217;re done with the encoding, free all resources with:<br />speex_bits_destroy(&amp;bits);<br />speex_encoder_destroy(enc_state);<br />That&#8217;s about it for the encoder.</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">使用Speex进行语音编码，首先要：</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">#include &lt; speex/speex.h &gt;</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">在代码中，需要声明Speex比特包结构体，同时设置Speex编码器状态：</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SpeexBits bits;</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">void * enc_state;</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">初始化两变量：</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_bits_init( &amp;bits );</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">enc_state = speex_encoder_init( &amp;speex_nb_mode );</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">用speex_wb_mode代替为speex_nb_mode，即可转换为宽带编码。很多时候，你在使用采样率的需要知道帧的大小，可以通过变量frame_size（用样本中的单位表示，不以字节为单位）获得，调用下面函数：</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_encoder_ctl( enc_state, SPEEX_GET_FRAME_SIZE, &amp;frame_size );</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">实践表明，在采用8、16或32kHz采样率的时候，frame_size大约对应于20ms。Speex编码器还有很多参数可以设置，其中最有用的一个是质量参数，控制着比特率（bit-rate）交换的质量，通过下面函数设置：</span></span><br /><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_encoder_ctl( enc_state, SPEEX_SET_QUALITY, &amp;quality );</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">quality是一个0～10（包含10）范围内的整数，窄带（narrowband）的质量和比特率（bit-rate）的对应关系如图9.2所示。</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">初始化成功后，对于每帧的输入：</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_bits_reset( &amp;bits );</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_encode_int( enc_state, input_frame, &amp;bits );</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">nbBytes = speex_bits_write( &amp;bits, byte_ptr, MAX_NB_BYTES );</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">其中，input_frame是指向每个Speex帧开始的short型指针，byte_ptr是将写入已被编码的帧的char型指针，MAX_NB_BYTES是byte_ptr在不导致溢出时可被写入的最大字节数，nbBytes是byte_ptr实际被写入的字节数(编码大小以字节为单位)。在调用speex_bits_write之前，可能会通过speex_bits_nbytes(&amp;bits)返回的字节数获得需要被写入的字节数，也可能使用speex_encode()&nbsp;函数，它接受一个携带音频数据的float*型参数。不过这将使缺少浮点运算单元（FPU）的平台（如ARM）变的更为复杂。实际上，speex_encode和speex_encode_int()用同样的方法处理，编码器是否使用定点数取决于编译期的标志位，不由API来控制。</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">完成编码后，释放所有资源：</span></span><br /><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_bits_destroy( &amp;bits );</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_encoder_destroy( enc_state );</span></span></p>
<p><span style="font-size: 10.5pt"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">这是关于编码的部分。</span></span></span></p>
<p>&nbsp;&nbsp;</p>
<h2><a style="color: rgb(51,102,153); text-decoration: none" name="t1"></a><a style="color: rgb(51,102,153); text-decoration: none" name="Decoding"></a>5.2&nbsp;<span style="font-family: 黑体">解码</span></h2>
<p><span style="font-size: small">In order to decode speech using Speex, you first need to:<br />#include &lt;speex/speex.h&gt;<br />You also need to declare a Speex bit-packing struct<br />SpeexBits bits;<br />and a Speex decoder state<br />void *dec_state;<br />The two are initialized by:<br />speex_bits_init(&amp;bits);<br />dec_state = speex_decoder_init(&amp;speex_nb_mode);<br />For wideband decoding, speex_nb_mode will be replaced by speex_wb_mode. If you need to obtain the size of the frames that will be used by the decoder, you can get that value in the frame_size variable (expressed in samples, not bytes) with:<br />speex_decoder_ctl(dec_state, SPEEX_GET_FRAME_SIZE, &amp;frame_size);<br />There is also a parameter that can be set for the decoder: whether or not to use a perceptual enhancer. This can be set by:<br />speex_decoder_ctl(dec_state, SPEEX_SET_ENH, &amp;enh);<br />where enh is an int with value 0 to have the enhancer disabled and 1 to have it enabled. As of 1.2-beta1, the default is now to enable the enhancer.<br />Again, once the decoder initialization is done, for every input frame:<br />speex_bits_read_from(&amp;bits, input_bytes, nbBytes);<br />speex_decode_int(dec_state, &amp;bits, output_frame);<br />where input_bytes is a (char *) containing the bit-stream data received for a frame, nbBytes is the size (in bytes) of that bit-stream, and output_frame is a (short *) and points to the area where the decoded speech frame will be written. A NULL value as the second argument indicates that we don&#8217;t have the bits for the current frame. When a frame is lost, the Speex decoder will do its best to "guess" the correct signal.<br />As for the encoder, the speex_decode() function can still be used, with a (float *) as the output for the audio. After you&#8217;re done with the decoding, free all resources with:<br />speex_bits_destroy(&amp;bits);<br />speex_decoder_destroy(dec_state);</span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif">使用Speex解码语音，首先要包含speex.h头文件。</span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">#include &lt; speex/speex.h&gt;</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">需要声明Speex比特包的结构体和Speex解码器的状态</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SpeexBits bits;</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">void* dec_state;</span></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">进行初始化</span></span></span></span><br /><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_bits_init( &amp;bits );</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">dec_state = speex_decoder_init( &amp;speex_nb_mode );</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">用speex_wb_mode代替speex_nb_mode，可转换为宽带（windband）解码。可能过变量frame_size来获得解码的帧大小</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_decoder_ctl( dec_state, SPEEX_GET_FRAME_SIZE, &amp;frame_size );</span></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">还可以能过下面函数设置是否使用&#8220;知觉增强&#8221;功能</span></span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_decoder_ctl( dec_state, SPEEX_SET_ENH, &amp;enh );</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">如果enh是0则表是不启用，1则表示启用。在1.2-beta1中，默认是开启的。</span></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">做完初始化工作后，则可对每个输入帧进行如下操作：</span></span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_bits_read_from( &amp;bits, input_bytes, nbBytes );</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_decode_int( dec_state, &amp;bits, output_frame );</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">其中,input_bytes是char型指针，包含了一帧的比特流数据，nbBytes是那帧比特流数据的大小（以字节为单位），output_frame是short型指针，指向一块内存区域，存储对语音帧的解码。第二个参数为空值（NULL）意味着没有获得到正确的比特(bit)数据，出现丢帧，Speex解码器会尽可能猜测最为准确的语音信号。</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">和编码器类似，可以用speex_decode()函数的一个float*型参数获得音频输出。</span></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">完成解码后，释放掉所有资源：</span></span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_bits_destory( &amp;bits );</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">speex_decoder_destory( dec_state );</span></span></span></p>
<p>&nbsp;</p>
<h2><a style="color: rgb(51,102,153); text-decoration: none" name="t2"></a><a style="color: rgb(51,102,153); text-decoration: none" name="CodecOption"></a>5.3&nbsp;<span style="font-family: 黑体">编解码选项</span>(speex_*_ctl)</h2>
<p><span style="font-size: small">The Speex encoder and decoder support many options and requests that can be accessed through the speex_encoder_ctl and<br />speex_decoder_ctl functions. These functions are similar to the ioctl system call and their prototypes are:<br />void speex_encoder_ctl(void *encoder, int request, void *ptr);<br />void speex_decoder_ctl(void *encoder, int request, void *ptr);<br />Despite those functions, the defaults are usually good for many applications and optional settings should only be used when one understands them and knows that they are needed. A common error is to attempt to set many unnecessary settings.<br />Here is a list of the values allowed for the requests. Some only apply to the encoder or the decoder. Because the last argument is of type void *, the _ctl() functions are not type safe, and shoud thus be used with care. The type spx_int32_t is the same as the C99 int32_t type.<br />SPEEX_SET_ENH&#8225; Set perceptual enhancer to on (1) or off (0) (spx_int32_t, default is on)<br />SPEEX_GET_ENH&#8225; Get perceptual enhancer status (spx_int32_t)<br />SPEEX_GET_FRAME_SIZE Get the number of samples per frame for the current mode (spx_int32_t)<br />SPEEX_SET_QUALITY&#8224; Set the encoder speech quality (spx_int32_t from 0 to 10, default is 8)<br />SPEEX_GET_QUALITY&#8224; Get the current encoder speech quality (spx_int32_t from 0 to 10)<br />SPEEX_SET_MODE&#8224; Set the mode number, as specified in the RTP spec (spx_int32_t)<br />SPEEX_GET_MODE&#8224; Get the current mode number, as specified in the RTP spec (spx_int32_t)<br />SPEEX_SET_VBR&#8224; Set variable bit-rate (VBR) to on (1) or off (0) (spx_int32_t, default is off)<br />SPEEX_GET_VBR&#8224; Get variable bit-rate (VBR) status (spx_int32_t)<br />SPEEX_SET_VBR_QUALITY&#8224; Set the encoder VBR speech quality (float 0.0 to 10.0, default is 8.0)<br />SPEEX_GET_VBR_QUALITY&#8224; Get the current encoder VBR speech quality (float 0 to 10)<br />SPEEX_SET_COMPLEXITY&#8224; Set the CPU resources allowed for the encoder (spx_int32_t from 1 to 10, default is 2)<br />SPEEX_GET_COMPLEXITY&#8224; Get the CPU resources allowed for the encoder (spx_int32_t from 1 to 10, default is 2)<br />SPEEX_SET_BITRATE&#8224; Set the bit-rate to use the closest value not exceeding the parameter (spx_int32_t in bits per second)<br />SPEEX_GET_BITRATE Get the current bit-rate in use (spx_int32_t in bits per second)<br />SPEEX_SET_SAMPLING_RATE Set real sampling rate (spx_int32_t in Hz)<br />SPEEX_GET_SAMPLING_RATE Get real sampling rate (spx_int32_t in Hz)<br />SPEEX_RESET_STATE Reset the encoder/decoder state to its original state, clearing all memories (no argument)<br />SPEEX_SET_VAD&#8224; Set voice activity detection (VAD) to on (1) or off (0) (spx_int32_t, default is off)<br />SPEEX_GET_VAD&#8224; Get voice activity detection (VAD) status (spx_int32_t)<br />SPEEX_SET_DTX&#8224; Set discontinuous transmission (DTX) to on (1) or off (0) (spx_int32_t, default is off)<br />SPEEX_GET_DTX&#8224; Get discontinuous transmission (DTX) status (spx_int32_t)<br />SPEEX_SET_ABR&#8224; Set average bit-rate (ABR) to a value n in bits per second (spx_int32_t in bits per second)<br />SPEEX_GET_ABR&#8224; Get average bit-rate (ABR) setting (spx_int32_t in bits per second)<br />SPEEX_SET_PLC_TUNING&#8224; Tell the encoder to optimize encoding for a certain percentage of packet loss (spx_int32_t in percent)<br />SPEEX_GET_PLC_TUNING&#8224; Get the current tuning of the encoder for PLC (spx_int32_t in percent)<br />SPEEX_SET_VBR_MAX_BITRATE&#8224; Set the maximum bit-rate allowed in VBR operation (spx_int32_t in bits per second)<br />SPEEX_GET_VBR_MAX_BITRATE&#8224; Get the current maximum bit-rate allowed in VBR operation (spx_int32_t in bits per second)<br />SPEEX_SET_HIGHPASS Set the high-pass filter on (1) or off (0) (spx_int32_t, default is on)<br />SPEEX_GET_HIGHPASS Get the current high-pass filter status (spx_int32_t)<br />&#8224; applies only to the encoder<br />&#8225; applies only to the decoder</span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif">Speex编码器和解码器可以通过访问speex_encoder_ctl和speex_decoder_ctl函数来设置更多选项，类似于系统函数ioctl。它们的原型是：</span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">void speex_encoder_ctl( void* encoder, int request, void* ptr );</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">void speex_decoder_ctl( void* decoder, int request, void* ptr );</span></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">尽管拥有这些函数，但一般的应用程序在默认情况下就足够，如果要设置则需了解并知道为什么需要它们，勿随变设置。</span></span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">下面列出了各种需求的允许值，其中一些只能应用于编码器或解码器。因为最后一个参数是void指针，所以_ctl()函数不是类型安全的，应小心使用。spx_int32_t类型同C99中的int32_t。</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_ENH：设置知觉增强，1开启，0关闭（spx_int32_t，默认开启）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_ENH：获得知觉增强状态( spx_int32_t)</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_QUALITY：设置编码质量（spx_int32_t&nbsp;从0～10，默认为8&nbsp;）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_QUALITY：获得当前语音编码质量（spx_int32_t&nbsp;从0～10&nbsp;）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_MODE：设置模式，指明RTP协议规格（spx_int32_t）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_MODE：获得当前模式，指明的RTP协议规格（spx_int32_t）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_VBR：设置变比特率（VBR），1开启，0关闭（spx_int32_t，&nbsp;默认关闭）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_VBR：&nbsp;获得变比特率功能当前是否开启（spx_int32_t&nbsp;）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_VBR_QUALITY：设置变比特率语音的编码质量（浮点数从0.0～10.0,默认8.0）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_VBR_QUALITY：获得当前变比特率语音的编码质量（&nbsp;浮点数从0.0～10.0）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_COMPLEXITY：设置编码器的可用CPU资源（&nbsp;spx_int32_t从1～10，默认为2）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_COMPLEXITY：获取编码器的可用CPU资源（spx_int32_t从1～10，默认为2）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_BITRATE：设置不超过参数设置的最佳比特值(spx_int32_t&nbsp;单位bits/s )</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_BITRATE：获取当前使用的比特率（&nbsp;spx_int32_t&nbsp;单位&nbsp;bits/s）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_SAMPLING_RATE：设置实时采样率（spx_int32_t&nbsp;单位&nbsp;Hz&nbsp;）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_SAMPLING_RATE：获取实时采样率（spx_int32_t&nbsp;单位&nbsp;Hz）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_RESET_STATE：重置编/解码器到原始状态，并清除所有记忆（无参数）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_VAD：设置静音检测特性（VAD），1为打开，0为关闭（&nbsp;spx_int32_t,&nbsp;默认为关闭）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_VAD：获取静音检测是否打开（&nbsp;spx_int32_t&nbsp;）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_DTX：设计非连续性传输（DTX），1为打开，0为关闭（spx_int32_t,&nbsp;默认为关闭）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_DTX：获取非连续性传输（DTX）是否打开（spx_int32_t&nbsp;）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_ABR：设置平均比特率（ABR）值，&nbsp;单位&nbsp;bits/s(spx_int32_t，单位&nbsp;bits/s )</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_ABR：获得平均比特率设置（spx_int32_t，单位bits/s&nbsp;）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_PLC_TUNING：让编码器对一定的失包率开启最优化编码（spx_int32_t，单位&nbsp;％）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_PLC_TUNING：<span style="font-family: 宋体">获取编码器为<span style="font-family: 'Times New Roman'">PLC</span><span style="font-family: 宋体">的当前调整（</span><span style="font-family: 'Times New Roman'">spx_int32_t</span><span style="font-family: 宋体">，单位％）</span></span></span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_VBR_MAX_BITRATE：设置允许变比特率（VBR）使用的最大比特率（spx_int32_t，单位&nbsp;bits/s&nbsp;）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_VBR_MAX_BITRATE：获取允许变比特率（VBR）使用的最大比特率（spx_int32_t，单位&nbsp;bits/s&nbsp;）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SET_HIGHPASS：设置高通滤波器，1为打开，0为关闭（spx_int32_t，默认为打开）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_GET_HIGHPASS：获取高通滤波器状态（&nbsp;spx_int32_t&nbsp;）</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">仅用于编/解码器。</span></span></span></p>
<p>&nbsp;</p>
<h2><a style="color: rgb(51,102,153); text-decoration: none" name="t3"></a><span style="font-family: Arial"><a style="color: rgb(51,102,153); text-decoration: none" name="ModeQuery"></a>5.4&nbsp;</span><span style="font-family: 黑体">模式查询</span></h2>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">Speex modes have a query system similar to the speex_encoder_ctl and speex_decoder_ctl calls. Since modes are read-only,it is only possible to get information about a particular mode. The function used to do that is:<br />void speex_mode_query(SpeexMode *mode, int request, void *ptr);</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">类似于调用speex_encoder_ctl和speex_decoder_ctl，Speex有模式查询系统。因为模式是只读的，所以只能获得模式的详细信息。使用如下函数：</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">void speex_mode_query( SpeexMode* mode, int request, void* ptr );</span></span></p>
<p>&nbsp;</p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">The admissible values for request are (unless otherwise note, the values are returned through ptr):<br />SPEEX_MODE_FRAME_SIZE Get the frame size (in samples) for the mode<br />SPEEX_SUBMODE_BITRATE Get the bit-rate for a submode number specified through ptr (integer in bps).</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">受理的请求值（除非另有说明，要不返回值都是通过ptr）：</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_MODE_FRAME_SIZE&nbsp;获得模式的帧大小(样本中)</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">SPEEX_SUBMODE_BITRATE：获取通过ptr指定的子模式数量的比特率（以bps为单位的整数）</span></span></p>
<p>&nbsp;</p>
<h2><a style="color: rgb(51,102,153); text-decoration: none" name="t4"></a><a style="color: rgb(51,102,153); text-decoration: none" name="Packing&amp;In-band Signalling"></a>5.5&nbsp;<span style="font-family: 黑体">封包和带内信令</span></h2>
<p><span style="font-size: small">Sometimes it is desirable to pack more than one frame per packet (or other basic unit of storage). The proper way to do it is to call speex_encode N times before writing the stream with speex_bits_write. In cases where the number of frames is not determined by an out-of-band mechanism, it is possible to include a terminator code. That terminator consists of the code 15 (decimal) encoded with 5 bits, as shown in Table 9.2. Note that as of version 1.0.2, calling speex_bits_write automatically inserts the terminator so as to fill the last byte. This doesn&#8217;t involves any overhead and makes sure Speex can always detect when there is no more frame in a packet.</span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif">有时我们打包的数据不只一帧（或其他基本存储单元），正确做法是在用speex_bits_write写入流数据之前调用N次speex_encode。这种情况下的帧数不是由带外机制决定的，它会包含一个终结码。如表9.2所示，这个终结码是由用5bits编码的Mode 15组成。如果是1.0.2版本需注意，调用speex_bits_write时，为了填充最后字节，它会自动添加终结码。这不会增加开销，并能确保Speex一直检测到包中没有更多帧为止。</span></span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体"><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">It is also possible to send in-band &#8220;messages&#8221; to the other side. All these messages are encoded as &#8220;pseudo-frames&#8221; of mode 14 which contain a 4-bit message type code, followed by the message. Table 5.1 lists the available codes, their meaning and the size of the message that follows. Most of these messages are requests that are sent to the encoder or decoder on the other end, which is free to comply or ignore them. By default, all in-band messages are ignored.</span></span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">当然也可以通过带内&#8220;消息&#8221;的方法，所有这些消息是作为Mode14的&#8220;伪帧&#8221;编码的，Mode14包含4bit的消息类型代码。表5.1列出了可用代码的说明和大小，发送给编/解码器的的消息大部分都可随意的被接受或被忽略。默认情况下，所有带内消息都被忽略掉了。</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small"><img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="In-band signalling codes" src="http://p.blog.csdn.net/images/p_blog_csdn_net/DotScylla/EntryImages/20090808/In-band%20signalling%20codes.jpg" width="663" height="367" /></span></span></span></p>
<p>&nbsp;</p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">表5.1&nbsp;带内信号代码</span></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">Finally, applications may define custom in-band messages using mode 13. The size of the message in bytes is encoded with 5 bits, so that the decoder can skip it if it doesn&#8217;t know how to interpret it.</span></span></span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">最后，一些应用会使用Mode 13自定义带内消息，消息的字节大小是用5bits编码的，所以如果编码器不知道如何解析它就会跳过。</span></span></span></p>
<p>&nbsp;</p>
<p><strong><a style="color: rgb(51,102,153); text-decoration: none" name="Markup"></a><span style="font-size: large">补充：</span></strong></p>
<p><span style="font-size: small">本是第9章--Speex窄带模式中的图和表格，但本章中需要参考，贴上来</span></p>
<p><span style="font-size: small"><img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="Analysis-by-synthesis closed-loop optimization on a sub-frame" src="http://p.blog.csdn.net/images/p_blog_csdn_net/DotScylla/EntryImages/20090808/Analysis-by-synthesis%20closed-loop%20optimization%20on%20a%20sub-frame.jpg" width="421" height="595" /></span></p>
<p><span style="font-size: small">Figure 9.2: Analysis-by-synthesis closed-loop optimization on a sub-frame.</span></p>
<p>&nbsp;</p>
<p><span style="font-size: small">&nbsp;<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="Quality versus bit rate" src="http://p.blog.csdn.net/images/p_blog_csdn_net/DotScylla/EntryImages/20090808/Quality%20versus%20bit%20rate.jpg" width="711" height="366" /></span></p>
<p><span style="font-size: small">Table 9.2: Quality versus bit-rate</span></p>
<p>&nbsp;</p>
<p><span style="font-size: small"><strong><a style="color: rgb(51,102,153); text-decoration: none" name="PostScript"></a><span style="font-size: large">后记</span>：</strong></span></p>
<p><span style="font-size: small">因为时间问题(英语学的太菜，翻译对偶来说是件困难的事情)，所以直接到第5章了，第3章--编译和移植和第4章--编/解码器命令行以后再进行翻译整理。</span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/dotscylla/article/details/4426220#Packing&amp;In-band Signalling"></a></span></span></p>
<p>&nbsp;</p>
<p>&nbsp;</p></div><br /><br /><br /></div><img src ="http://www.cppblog.com/tx7do/aggbug/195513.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-22 00:03 <a href="http://www.cppblog.com/tx7do/archive/2012/11/22/195513.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Speex手册----编解码介绍</title><link>http://www.cppblog.com/tx7do/archive/2012/11/22/195512.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Wed, 21 Nov 2012 16:01:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/22/195512.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195512.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/22/195512.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195512.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195512.html</trackback:ping><description><![CDATA[<div><strong>转载自:</strong><a href="http://blog.csdn.net/DotScylla/article/details/4402688"><strong>http://blog.csdn.net/DotScylla/article/details/4402688</strong></a>
<div style="border-bottom: rgb(204,204,204) 1px solid; min-width: 200px; text-align: left; border-left: rgb(204,204,204) 1px solid; padding-bottom: 4px; widows: 2; text-transform: none; background-color: rgb(238,238,238); text-indent: 0px; padding-left: 10px; padding-right: 10px; font: 12px Arial, Console, Verdana, 'Courier New'; white-space: normal; orphans: 2; float: left; letter-spacing: normal; color: rgb(51,51,51); border-top: rgb(204,204,204) 1px solid; border-right: rgb(204,204,204) 1px solid; word-spacing: 0px; padding-top: 4px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-origin: initial; background-clip: initial; border-image: initial">
<p style="text-align: right; margin: 0px"><span style="float: left"><strong>目录</strong><a style="color: rgb(51,102,153); text-decoration: none" title="系统根据文章中H1到H6标签自动生成文章目录" href="http://blog.csdn.net/DotScylla/article/details/4402688#"><strong>(?)</strong></a></span><a style="color: rgb(51,102,153); text-decoration: none" title="收起" onclick="javascript:return openct(this);" href="http://blog.csdn.net/DotScylla/article/details/4402688#"><strong>[-]</strong></a></p>
<ol style="line-height: 19px; padding-left: 14px; margin-left: 14px"><li><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#t0"><strong>概念</strong></a></li><li><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#t1"><strong>编解码</strong></a></li><li><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#t2"><strong>预处理器</strong></a></li><li><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#t3"><strong>自适应抖动缓冲</strong></a></li><li><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#t4"><strong>回声消除</strong></a></li><li><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#t5"><strong>重采样</strong></a></li></ol></div>
<div style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 12px Arial, Console, Verdana, 'Courier New'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); clear: both; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"></div>
<div style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 20px 0px 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" id="article_content">
<div><span style="font-family: 宋体"><span style="font-family: 黑体"><span style="font-size: small">
<p><span style="font-family: 宋体"><strong>前言：</strong>Speex官网：<a style="color: rgb(51,102,153); text-decoration: none" href="http://speex.org/"><span style="color: rgb(51,102,153)"><span style="font-size: small">http://speex.org/</span></span></a><span style="font-size: small">&nbsp;可以再Documentation下找到PDF版或HTML OL版的英文手册。可能会由于英文技能的匮乏或语音解码领域的不熟悉会有翻译错误，所以每段我都会付上英文原段落，也望各位发现后能够不吝赐教，大家共同进步。</span></span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体"><span style="font-size: small">PS:如需转载，注明出处，不胜感激</span></span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#conception">2.1 概念</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small">&nbsp;&nbsp;&nbsp;&nbsp;<a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#sampler">采样率</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small">&nbsp;&nbsp;&nbsp;&nbsp;<a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#bit-rate">比特率</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small">&nbsp;&nbsp;&nbsp;&nbsp;<a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#quality">质量(可变）</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small">&nbsp;&nbsp;&nbsp;&nbsp;<a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#complexity">复杂度(可变)</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small">&nbsp;&nbsp;&nbsp;&nbsp;<a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#variablebit-rate">变比特率</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small">&nbsp;&nbsp;&nbsp;&nbsp;<a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#averageBit-Rate">平均比特率</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small">&nbsp;&nbsp;&nbsp;&nbsp;<a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#VoiceActivity">静音检测</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small">&nbsp;&nbsp;&nbsp;&nbsp;<a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#Disconnection">非连续性传输</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small">&nbsp;&nbsp;&nbsp;&nbsp;<a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#Perceptual">知觉增强</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small">&nbsp;&nbsp;&nbsp;&nbsp;<a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#Algorithmic">延时算法</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#Codec">2.2 编解码</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#Preprocessor">2.3 预处理器</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#JitterBuffer">2.4 自适应抖动缓冲</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#EchoCanceller">2.5 回声消除</a></span></span></p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#Resampler">2.6 重采样</a></span></span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体"><span style="font-size: small"><a style="color: rgb(51,102,153); text-decoration: none" href="http://blog.csdn.net/DotScylla/article/details/4402688#PostScript">后记</a></span></span></p></span></span></span>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">This section describes Speex and its features into more details</span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif">这部分详细介绍Speex及其特性</span></span></p>
<h2><a style="color: rgb(51,102,153); text-decoration: none" name="t0"></a><span style="font-size: large"><span style="font-family: Arial"><a style="color: rgb(51,102,153); text-decoration: none" name="conception"></a>2.1&nbsp;</span><span style="font-family: 黑体">概念</span></span></h2>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif">Before introducing all the Speex features, here are some concepts in speech coding that help better understand the rest of the manual. Although some are general concepts in speech/audio processing, others are specific to Speex</span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif">在介绍Speex特性之前，为了便于阅读后面的文档，需要解释一些概念，尽管一些概念是在语音/音频处理过程中常见的，但也有Speex特有的一些。</span></span></p>
<p>&nbsp;</p>
<p><strong><span style="font-size: small"><span style="font-family: 宋体"><a style="color: rgb(51,102,153); text-decoration: none" name="sampler"></a>采样率</span></span></strong></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif">The sampling rate expressed in Hertz (Hz) is the number of samples taken from a signal per second. For a sampling rate of Fs kHz, the highest frequency that can be represented is equal to Fs/2 kHz (Fs/2 is known as the Nyquist frequency). This is a fundamental property in signal processing and is described by the sampling theorem. Speex is mainly designed for three different sampling rates: 8 kHz, 16 kHz, and 32 kHz. These are respectively refered to as narrowband, wideband and ultra-wideband.</span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">采样率是指从连续信号中每秒钟采集到的采样数量。用Fs kHz来表示，最高频率可表示为Fs/2 kHz（见奈奎斯特Nyquist频率）。采样定理表明这是信号处理最基本的属性。Speex主要设计了三种不同的采样率：8kHz，16kHz和32kHz。分别表示了窄带、宽带和超宽带。</span></span></span></p>
<p>&nbsp;</p><strong><span style="font-size: small"><span style="font-family: 宋体">
<p><a style="color: rgb(51,102,153); text-decoration: none" name="bit-rate"></a>比特率<span style="font-size: small">&nbsp;</span><strong>&nbsp;</strong></p></span></span></strong>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">When encoding a speech signal, the bit-rate is defined as the number of bits per unit of time required to encode the speech. It is measured in bits per second (bps), or generally kilobits per second. It is important to make the distinction between kilobits per second (kbps) and kilobytes per second (kBps).</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">比特率是指每秒钟传送的比特数，在语音信号编码时，表示语音数据每秒钟需要多少个比特表示，单位为bps(比特/秒)或kbps(千比特/秒)。注意区分kbps和kBps（千字节/秒）。</span></span></p><strong>
<p>&nbsp;</p>
<p><span style="font-size: small"><span style="font-family: 宋体"><a style="color: rgb(51,102,153); text-decoration: none" name="quality"></a>质量</span><span style="font-family: 'Times New Roman'">(</span>可变<span style="font-family: 'Times New Roman'">)</span></span></p></strong>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif">Speex is a lossy codec, which means that it achives compression at the expense of fidelity of the input speech signal. Unlike ome other speech codecs, it is possible to control the tradeoff made between quality and bit-rate. The Speex encoding process is controlled most of the time by a quality parameter that ranges from 0 to 10. In constant bit-rate (CBR) operation, the quality parameter is an integer, while for variable bit-rate (VBR), the parameter is a float.</span></span></p>
<p><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">Speex是一种有损编解码库，这意味着它的文档压缩方面会导致语音输入信号的失真，和一些语音编解码库不同的是，它尽可能的去控制质量和比特率之间的平衡。大多数时候，是用一个0到10范围内的质量参数来控制Speex的编码，比特率为常量的操作，质量参数是整数，如果是变比特率（VBR），则为浮点数（Float）</span></span></p><strong>
<p>&nbsp;</p>
<p><span style="font-size: small"><span style="font-family: 宋体"><a style="color: rgb(51,102,153); text-decoration: none" name="complexity"></a>复杂度（可变）</span></span></p></strong>
<p><span style="font-size: small">With Speex, it is possible to vary the complexity allowed for the encoder. This is done by controlling how the search is performed with an integer ranging from 1 to 10 in a way that&#8217;s similar to the -1 to -9 options to gzip and bzip2 compression utilities. For normal use, the noise level at complexity 1 is between 1 and 2 dB higher than at complexity 10, but the CPU requirements for complexity 10 is about 5 times higher than for complexity 1. In practice, the best trade-off is between complexity 2 and 4, though higher settings are often useful when encoding non-speech sounds like DTMF tones.</span></p>
<p><span style="font-size: small">在Speex中，编码器可调整复杂度。用1到10的整数来控制如何执行搜索，就像用-1到-9来设置压缩工具gzip或bzip2(博主注：设计压缩的块长度,为100k～900k)。正常情况下，复杂度为1时噪声级会比复杂度为10时高1～2 dB(分贝)，而复杂度为10的CPU需求是复杂度为1的5倍。实践证明，最好将复杂度设置在2～4，设置较高则对非语音编码如双音多频（DTMF）音质较为有用。</span></p><strong>
<p>&nbsp;</p>
<p><span style="font-size: small"><span style="font-family: 宋体"><a style="color: rgb(51,102,153); text-decoration: none" name="variablebit-rate"></a>变比特率（</span><span style="font-family: 'Times New Roman'">VBR</span>）</span></p></strong>
<p><span style="font-size: small">Variable bit-rate (VBR) allows a codec to change its bit-rate dynamically to adapt to the &#8220;difficulty&#8221; of the audio being encoded. In the example of Speex, sounds like vowels and high-energy transients require a higher bit-rate to achieve good quality, while fricatives (e.g. s,f sounds) can be coded adequately with less bits. For this reason, VBR can achive lower bit-rate for the same quality, or a better quality for a certain bit-rate. Despite its advantages, VBR has two main drawbacks: first, by only specifying quality, there&#8217;s no guaranty about the final average bit-rate. Second, for some real-time applications like voice over IP (VoIP), what counts is the maximum bit-rate, which must be low enough for the communication channel.</span></p>
<p><span style="font-size: small">变比牲率（VBR）允许编解码器动态调整比特率以适应的音频解码的&#8220;难度&#8221;，拿Speex来说，像元音和瞬间高音则需较高比特率（Bit-rate）来达到最佳效果，而摩擦音则用较少的比特（bits）即可完成编码。基于这种原因，变比特率（VBR）可以用较低的比特率(bit-rate)达到相同的效果或使用某比特率（bit-rate）质量会更好。尽管它有这些优势，但VBR也有两个主要的缺点：首先，它只是针对质量，却没办法保证最终的平均比特率（ABR）; 其次，在一些实时应用如VOIP电话中，尽管拥有高的比特率（bit-rate），为适应通信信道还是需要适当降低。</span></p><strong>
<p>&nbsp;</p>
<p><span style="font-size: small"><span style="font-family: 宋体"><a style="color: rgb(51,102,153); text-decoration: none" name="averageBit-Rate"></a>平均比特率（</span><span style="font-family: 'Times New Roman'">ABR</span>）</span></p></strong>
<p><span style="font-size: small">Average bit-rate solves one of the problems of VBR, as it dynamically adjusts VBR quality in order to meet a specific target bit-rate. Because the quality/bit-rate is adjusted in real-time (open-loop), the global quality will be slightly lower than that obtained by encoding in VBR with exactly the right quality setting to meet the target average bit-rate.</span></p>
<p><span style="font-size: small">平均比特率（ABR）通过动态调整变比特率(VBR)的质量来获得一个特定目标的比特率，解决了VBR中存在的问题之一。因为平均比特率（ABR）是实时（开环）调整质量/比特率(bit-rate)的，整体质量会略低于通过变比特率（VBR）设置的接近于目标平均比特率进行编码获得的质量。</span></p><strong>
<p>&nbsp;</p>
<p><span style="font-size: small"><span style="font-family: 宋体"><a style="color: rgb(51,102,153); text-decoration: none" name="VoiceActivity"></a>静音检测（</span><span style="font-family: 'Times New Roman'">VAD</span>）</span></p></strong>
<p><span style="font-size: small">When enabled, voice activity detection detects whether the audio being encoded is speech or silence/background noise. VAD is always implicitly activated when encoding in VBR, so the option is only useful in non-VBR operation. In this case, Speex detects non-speech periods and encode them with just enough bits to reproduce the background noise. This is called &#8220;comfort noise generation&#8221; (CNG).</span></p>
<p><span style="font-size: small">静音检测（VAD）将检测被编码的音频数据是语音还是静音或背景噪声。这个特性在用变比特率（VBR）进行编码是总是开启的，所以选项设置只对非变比特率（VBR）起作用。在这种情况下，Speex检测非语音周期并对用足够的比特数重新生成的背景噪声进行编码。这个叫&#8220;舒适噪声生成（CNG）&#8221;。</span></p><strong>
<p>&nbsp;</p>
<p><span style="font-size: small"><span style="font-family: 宋体"><a style="color: rgb(51,102,153); text-decoration: none" name="Disconnection"></a>非连续传输（</span><span style="font-family: 'Times New Roman'">DTX</span>）</span></p></strong>
<p><span style="font-size: small">Discontinuous transmission is an addition to VAD/VBR operation, that allows to stop transmitting completely when the background noise is stationary. In file-based operation, since we cannot just stop writing to the file, only 5 bits are used for such frames (corresponding to 250 bps).</span></p>
<p><span style="font-size: small">非连续性传输（DTX）是静音检测（VAD）/变比特率（VBR）操作的额外选项，它能够在背景噪声固定时，完全的停止传输。如果是基于文件的操作，由于我们不能停止对文件的写入，会有5个比特被用到这种帧内（相对于250bps）。</span></p><strong>
<p>&nbsp;</p>
<p><span style="font-size: small"><span style="font-family: 宋体"><a style="color: rgb(51,102,153); text-decoration: none" name="Perceptual"></a>知觉增强</span></span></p></strong>
<p><span style="font-size: small">Perceptual enhancement is a part of the decoder which, when turned on, attempts to reduce the perception of the noise/distortion produced by the encoding/decoding process. In most cases, perceptual enhancement brings the sound further from the original objectively (e.g. considering only SNR), but in the end it still sounds better (subjective improvement).</span></p>
<p><span style="font-size: small">知觉增强中解码的一部分，开启后，用来减少在编码/解码过程中产生的噪音/失真。大多数情况下，知觉增强产生的会和最原始的声音会相差较远（如只考虑信噪比（SNR）），但最后发音效果却很好（主观改善）。</span></p><strong>
<p>&nbsp;</p>
<p><span style="font-size: small"><span style="font-family: 宋体"><a style="color: rgb(51,102,153); text-decoration: none" name="Algorithmic"></a>延时算法</span></span></p></strong>
<p><span style="font-size: small">Every speech codec introduces a delay in the transmission. For Speex, this delay is equal to the frame size, plus some amount of &#8220;look-ahead&#8221; required to process each frame. In narrowband operation (8 kHz), the delay is 30 ms, while for wideband (16 kHz), the delay is 34 ms. These values don&#8217;t account for the CPU time it takes to encode or decode the frames.</span></p>
<p><span style="font-size: small">每个声音编解码在传输过程中都会有时延。就Speex来说，它的时延就等于每帧大小加上每帧需要处理的一些"预测"(look-ahead)。在窄带(8kHz)操作中,大概30ms时延，宽带操作大概34ms时延。而且没有将CPU进行编/解码的时间计算在内。</span></p><strong>
<h2><a style="color: rgb(51,102,153); text-decoration: none" name="t1"></a><span style="font-size: large"><span style="font-family: Arial"><a style="color: rgb(51,102,153); text-decoration: none" name="Codec"></a>2.2&nbsp;</span><span style="font-family: 黑体">编解码</span></span></h2></strong>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif">The main characteristics of Speex can be summarized as follows:<br />&nbsp;&nbsp;&nbsp; &#8226; Free software/open-source, patent and royalty-free<br />&nbsp;&nbsp;&nbsp; &#8226;&nbsp;Integration of narrowband and wideband using an embedded bit-stream<br />&nbsp;&nbsp;&nbsp; &#8226; Wide range of bit-rates available (from 2.15 kbps to 44 kbps)<br />&nbsp;&nbsp;&nbsp; &#8226; Dynamic bit-rate switching (AMR) and Variable Bit-Rate (VBR) operation<br />&nbsp;&nbsp;&nbsp; &#8226; Voice Activity Detection (VAD, integrated with VBR) and discontinuous transmission (DTX)<br />&nbsp;&nbsp;&nbsp; &#8226; Variable complexity<br />&nbsp;&nbsp;&nbsp; &#8226; Embedded wideband structure (scalable sampling rate)<br />&nbsp;&nbsp;&nbsp; &#8226; Ultra-wideband sampling rate at 32 kHz<br />&nbsp;&nbsp;&nbsp; &#8226; Intensity stereo encoding option<br />&nbsp;&nbsp;&nbsp; &#8226; Fixed-point implementation</span></span></p>
<p><span style="font-size: small"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">Speex的主要特性总结如下：</span></span></span></p>
<ul><li>
<div style="text-indent: -21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">开源的自由软件，免专利，免版权</span></span></div></li><li>
<div style="text-indent: -21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">通过嵌入的比特流集成窄带和宽带</span></span></div></li><li>
<div style="text-indent: -21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">可大范围改变比特率（bit-rate）（从2.15kbps到44kbps ）</span></span></div></li><li>
<div style="text-indent: -21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">动态比特率交换（AMR）和变比特率（VBR）操作</span></span></div></li><li>
<div style="text-indent: -21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">静音检测（VAD，和变比特率（VBR）集成）和非连续性传输（DTX）</span></span></div></li><li>
<div style="text-indent: -21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">可变复杂度</span></span></div></li><li>
<div style="text-indent: -21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">嵌入的宽带结构（可变的比特率）</span></span></div></li><li>
<div style="text-indent: -21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">32kHz的超宽带采样率</span></span></div></li><li>
<div style="text-indent: -21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">强立体声编码选项</span></span></div></li><li>
<div style="text-indent: -21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-family: arial, helvetica, sans-serif"><span style="font-size: small">定点执行</span></span></div></li></ul><strong><span style="font-size: large"><span style="font-family: Arial">
<h2><a style="color: rgb(51,102,153); text-decoration: none" name="t2"></a><a style="color: rgb(51,102,153); text-decoration: none" name="Preprocessor"></a><span style="font-family: 黑体"><span style="font-size: large"><span style="font-family: Arial">2.3&nbsp;</span>预处理器</span></span></h2></span></span></strong>
<p><span style="font-size: small">This part refers to the preprocessor module introduced in the 1.1.x branch. The preprocessor is designed to be used on the<br />audio before running the encoder. The preprocessor provides three main functionalities:<br />&#8226; noise suppression<br />&#8226; automatic gain control (AGC)<br />&#8226; voice activity detection (VAD)</span></p>
<p><span style="font-size: small">这部分涉及到1.1.x里的预处理模块介绍，预处理器是在音频被编码前使用，它主要提供如下三种主要功能：</span></p>
<ul><li>
<div style="text-indent: -21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: small">抑制噪音</span></div></li><li>
<div style="text-indent: -21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: small">自动增益控制（AGC）</span></div></li><li>
<div style="text-indent: -21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: small">静音检测（VAD）</span></div></li></ul>
<p>&nbsp;</p>
<p><span style="font-size: small">The denoiser can be used to reduce the amount of background noise present in the input signal. This provides higher quality speech whether or not the denoised signal is encoded with Speex (or at all). However, when using the denoised signal with the codec, there is an additional benefit. Speech codecs in general (Speex included) tend to perform poorly on noisy input, which tends to amplify the noise. The denoiser greatly reduces this effect.</span></p>
<p><span style="font-size: small">降噪是用来减少输入信号中的背景噪音的数量。不论是Speex（或其他）编码的去噪信号可提供更高的语音质量。无论如何编解码器使用降噪信号都是有利的。一般的语音编解码器（Speex中也包含）在噪音输入方面都表现不佳，往往会扩大噪音。而降噪则大大降低了这种影响。</span></p>
<p>&nbsp;</p>
<p><span style="font-size: small">Automatic gain control (AGC) is a feature that deals with the fact that the recording volume may vary by a large amount between different setups. The AGC provides a way to adjust a signal to a reference volume. This is useful for voice over IP because it removes the need for manual adjustment of the microphone gain. A secondary advantage is that by setting the microphone gain to a conservative (low) level, it is easier to avoid clipping.</span></p>
<p><span style="font-size: small">不同的设备，录音效果会有较大幅度的变动，自动增益控制（AGC）就是用来处理这种现象的。它提供了一种调整信号为参考音量的方法。这对VOIP（voice over IP）是非常有用的，因为它不需要再手动去调整麦克风增益。第二个好处是，将麦克风增益设置为保守(低)级别，可有效避免削波。</span></p>
<p>&nbsp;</p>
<p><span style="font-size: small">The voice activity detector (VAD) provided by the preprocessor is more advanced than the one directly provided in the codec.</span></p>
<p><span style="font-size: small">预处理器提供的静音检测（VAD）比编解码器里直接提供的更为先进。</span></p>
<h2><a style="color: rgb(51,102,153); text-decoration: none" name="t3"></a><span style="font-size: large"><span style="font-family: Arial"><a style="color: rgb(51,102,153); text-decoration: none" name="JitterBuffer"></a>2.4&nbsp;</span><span style="font-family: 黑体">自适应抖动缓冲</span></span></h2>
<p><span style="font-size: small">When transmitting voice (or any content for that matter) over UDP or RTP, packet may be lost, arrive with different delay,or even out of order. The purpose of a jitter buffer is to reorder packets and buffer them long enough (but no longer than necessary) so they can be sent to be decoded.</span></p>
<p><span style="font-size: small">在用UDP或RTP协议传输语音（或其他相关内容）的时候，会出现丢包、不同时延甚至是非时序的到达。抖动缓冲的目的就是将它们缓冲到足够长（不超过必需的）并对这些包进行重排序，然后才送给解码器进行解码。</span></p>
<h2><a style="color: rgb(51,102,153); text-decoration: none" name="t4"></a><span style="font-size: large"><span style="font-family: Arial"><a style="color: rgb(51,102,153); text-decoration: none" name="EchoCanceller"></a>2.5&nbsp;</span><span style="font-family: 黑体">回声消除</span></span></h2>
<p align="center"><strong>&nbsp;</strong></p>
<p><strong><span style="font-size: small"><span style="font-family: 宋体"><img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="Acoustic Echo Model" src="http://p.blog.csdn.net/images/p_blog_csdn_net/DotScylla/EntryImages/20090803/EchoCanceller.JPG" width="516" height="271" /></span></span></strong></p>
<p><span style="font-size: small">图 2.1 回声模式</span></p>
<p><span style="font-size: small">In any hands-free communication system (Fig. 2.1), speech from the remote end is played in the local loudspeaker, propagates in the room and is captured by the microphone. If the audio captured from the microphone is sent directly to the remote end, then the remove user hears an echo of his voice. An acoustic echo canceller is designed to remove the acoustic echo before it is sent to the remote end. It is important to understand that the echo canceller is meant to improve the quality on the remote end.</span></p>
<p><span style="font-size: small">如图2.1所示，在免提通信系统中，语音从远端传回本地的扩音器，麦克风回捕获房内的回声，然后会将其直接发回给远端，远端用户就会听到它自己的声音。回声消除器就是为了在回声传回给远端用户之前将其消除。重要的是要明白，回声消除用来提高远端用户接收到的语音质量。</span></p>
<h2><a style="color: rgb(51,102,153); text-decoration: none" name="t5"></a><span style="font-size: large"><span style="font-family: Arial"><a style="color: rgb(51,102,153); text-decoration: none" name="Resampler"></a>2.6&nbsp;</span><span style="font-family: 黑体">重采样</span></span></h2>
<p><span style="font-size: small">In some cases, it may be useful to convert audio from one sampling rate to another. There are many reasons for that. It can be for mixing streams that have different sampling rates, for supporting sampling rates that the soundcard doesn&#8217;t support, for transcoding, etc. That&#8217;s why there is now a resampler that is part of the Speex project. This resampler can be used to convert between any two arbitrary rates (the ratio must only be a rational number) and there is control over the quality/complexity tradeoff.</span></p>
<p><span style="font-size: small">在一些情况下，改变音频的采样率是非常有用的。有很多原因，如拥有不同采样率则可进行混合流、支持声卡不支持的采样率、代码转换等。这是为什么重采样会成为Speex工程的一部分。重采样可在任意比率之间转换（比率必须是有理数），它是基于质量/复杂度进行的折中。&nbsp;</span></p>
<p><strong>&nbsp;</strong></p>
<p><span style="font-family: 宋体; font-size: 10.5pt"><a style="color: rgb(51,102,153); text-decoration: none" name="PostScript"></a><span style="font-size: small"><strong>后记：</strong></span></span></p>
<p>&nbsp;<span style="font-size: small">嗯，总体来说感觉翻译的蛮粗糙的，有些地方理解的不是很透，放在这里供大家拍砖。</span></p></div></div><br /><br /><br /><br /><br /><br /><br /></div><img src ="http://www.cppblog.com/tx7do/aggbug/195512.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-22 00:01 <a href="http://www.cppblog.com/tx7do/archive/2012/11/22/195512.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Speex手册----Speex 简介</title><link>http://www.cppblog.com/tx7do/archive/2012/11/21/195511.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Wed, 21 Nov 2012 15:59:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/21/195511.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195511.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/21/195511.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195511.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195511.html</trackback:ping><description><![CDATA[<div><strong style="color: red">转载自:</strong><a style="color: red" href="http://www.cnblogs.com/rosesmall/archive/2012/04/18/2455385.html"><strong>http://www.cnblogs.com/rosesmall/archive/2012/04/18/2455385.html</strong></a><br /><br />
<div style="widows: 2; text-transform: none; text-indent: 0px; font: 13px/19px Verdana, Geneva, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-break: normal !important; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" id="cnblogs_post_body">
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;前言：没搜到Speex相关的中文资料，所以想将Speex的英文手册中会用到的部分翻译出来。Speex官网：<a style="background-color: transparent; color: rgb(51,102,153); text-decoration: none; background-origin: initial; background-clip: initial" href="http://speex.org/">http://speex.org/</a>&nbsp;可以再Documentation下找到PDF版或HTML OL版的英文手册。每段我都会付上英文原段落，可能会由于英文技能的匮乏或语音解码领域的不熟悉会有翻译错误，也望各位发现后能够不吝赐教，大家共同进步。</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">PS:如需转载，注明出处，不胜感激</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">简介</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">1.1 获得帮助</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">1.2 关于此文档</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">后记</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">简介：</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">The Speex codec (<a style="background-color: transparent; color: rgb(51,102,153); text-decoration: none; background-origin: initial; background-clip: initial" href="http://www.speex.org/">http://www.speex.org/</a>) exists because there is a need for a speech codec that is open-source and free from software patent royalties. These are essential conditions for being usable in any open-source software. In essence,Speex is to speech what Vorbis is to audio/music. Unlike many other speech codecs, Speex is not designed for mobile phones but rather for packet networks and voice over IP (VoIP) applications. File-based compression is of course also supported.</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">由于语音对话编解码需要一个免费的开源软件，所以诞生了Speex库，可以在任何开源软件中使用。实际上，Speex对于语音对话来讲，相当于Vorbis[一种可将声音来源加以压缩的编码软件，开放源码且免版权]对于音频/音乐。和大多数语音编解码库不一样的是，Speex不是为移动电话而设计的，而是为分组网络的VOIP(Voice over IP)应用程序，同时支持基于文件的压缩。</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">The Speex codec is designed to be very flexible and support a wide range of speech quality and bit-rate. Support for very good quality speech also means that Speex can encode wideband speech (16 kHz sampling rate) in addition to narrowband speech (telephone quality, 8 kHz sampling rate).</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Speex编解码库的设计非常灵活，支持广泛的语音质量和比特率。良好的语音质量支持意味着除了窄带语音( 电话质量，8kHz采样率)外还可以对宽带语音( 电话质量，16kHz采样率)进行编解码。</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;&nbsp;&nbsp; Designing for VoIP instead of mobile phones means that Speex is robust to lost packets, but not to corrupted ones. This is based on the assumption that in VoIP, packets either arrive unaltered or don&#8217;t arrive at all. Because Speex is targeted at a wide range of devices, it has modest (adjustable) complexity and a small memory footprint.</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Speex被设计用于VoIP而不是移动电话，意味着Speex对于丢包能够妥善处理,不会有损坏数据。这在VOIP里是基于这样的假设，数据包要么不被改变的到达，要么不会到达。Speex针对于大多数的设备，因此它拥有适中（可调整）的复杂性和较小内存占用。</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;&nbsp; All the design goals led to the choice of CELP as the encoding technique. One of the main reasons is that CELP has long proved that it could work reliably and scale well to both low bit-rates (e.g. DoD CELP @ 4.8 kbps) and high bit-rates (e.g.G.728 @ 16 kbps).</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所有这些设计的目的是为了引入码激励线性预测(CELP)编码技术，因为长期实践表明它对于低比特率（如DoD CELP@ 4.8kbps）和高比特率（如G.728 @ 16kbps）的工作性能良好,可靠性高。</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">1.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 获得帮助<br />As for many open source projects, there are many ways to get help with Speex. These include:<br />&#8226; This manual<br />&#8226; Other documentation on the Speex website (<a style="background-color: transparent; color: rgb(51,102,153); text-decoration: none; background-origin: initial; background-clip: initial" href="http://www.speex.org/">http://www.speex.org/</a>)<br />&#8226; Mailing list: Discuss any Speex-related topic on&nbsp;<a style="background-color: transparent; color: rgb(51,102,153); text-decoration: none; background-origin: initial; background-clip: initial" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#112;&#101;&#101;&#120;&#45;&#100;&#101;&#118;&#64;&#120;&#105;&#112;&#104;&#46;&#111;&#114;&#103;">speex-dev@xiph.org</a>&nbsp;(not just for developers)<br />&#8226; IRC: The main channel is #speex on irc.freenode.net. Note that due to time differences, it may take a while to get someone, so please be patient.<br />&#8226; Email the author privately at&nbsp;<a style="background-color: transparent; color: rgb(51,102,153); text-decoration: none; background-origin: initial; background-clip: initial" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#106;&#101;&#97;&#110;&#45;&#109;&#97;&#114;&#99;&#46;&#118;&#97;&#108;&#105;&#110;&#64;&#117;&#115;&#104;&#101;&#114;&#98;&#114;&#111;&#111;&#107;&#101;&#46;&#99;&#97;">jean-marc.valin@usherbrooke.ca</a>&nbsp;only for private/delicate topics you do not wish to discuss publically.</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">类似于大多数开源项目，Speex也可以能过多种获得帮助的路径，包括：</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 本手册</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Speex官方站点（<a style="background-color: transparent; color: rgb(51,102,153); text-decoration: none; background-origin: initial; background-clip: initial" href="http://www.speex.org/">http://www.speex.org/</a>&nbsp;）的其他文档</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 邮件列表：讨论Speex相关发送至&nbsp;<a style="background-color: transparent; color: rgb(51,102,153); text-decoration: none; background-origin: initial; background-clip: initial" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#112;&#101;&#101;&#120;&#45;&#100;&#101;&#118;&#64;&#120;&#105;&#112;&#104;&#46;&#111;&#114;&#103;">speex-dev@xiph.org</a>&nbsp;(不是仅限于开发者)</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IRC：通过irc.freenode.net Speex频道获取，可能需要耐心等待一段时间</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果不想公开讨论一些主题，可Email作者<a style="background-color: transparent; color: rgb(51,102,153); text-decoration: none; background-origin: initial; background-clip: initial" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#106;&#101;&#97;&#110;&#45;&#109;&#97;&#114;&#99;&#46;&#118;&#97;&#108;&#105;&#110;&#64;&#117;&#115;&#104;&#101;&#114;&#98;&#114;&#111;&#111;&#107;&#101;&#46;&#99;&#97;">jean-marc.valin@usherbrooke.ca</a></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">Before asking for help (mailing list or IRC), it is important to first read this manual (OK, so if you made it here it&#8217;s already a good sign). It is generally considered rude to ask on a mailing list about topics that are clearly detailed in the documentation. On the other hand, it&#8217;s perfectly OK (and encouraged) to ask for clarifications about something covered in the manual. This manual does not (yet) cover everything about Speex, so everyone is encouraged to ask questions, send comments, feature requests, or just let us know how Speex is being used.</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">在寻求帮助前（邮件列表或IRC），最好先仔细阅读本手册（呵呵，看到这里说明你已经有一个不错的开始），如果文档中介绍的很详细的问题你仍然去Email多不好。当然，本手册也不可能囊括关于Speex所有的知识点，所以也希望大家多提问题和见解、以及需要改进或增加的功能，或者是仅仅让我们知道您在使用Speex。</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">Here are some additional guidelines related to the mailing list. Before reporting bugs in Speex to the list, it is strongly recommended (if possible) to first test whether these bugs can be reproduced using the speexenc and speexdec (see Section 4)<br />command-line utilities. Bugs reported based on 3rd party code are both harder to find and far too often caused by errors that have nothing to do with Speex.</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">在发送报告Bugs的邮件时，也对大家有些额外的要求，建议（如果可能）先使用Speexenc和Speexdec（见第4节）命令行工具测试能否使Bugs再现，很多报告的Bug都由第三方的代码引起而难以发现，造成的错误往往不关Speex的事。</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">1.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 关于此文档<br />This document is divided in the following way. Section 2 describes the different Speex features and defines many basic terms that are used throughout this manual. Section 4 documents the standard command-line tools provided in the Speex distribution. Section 5 includes detailed instructions about programming using the libspeex API. Section 7 has some information related to Speex and standards.</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">文档分为几部分，第2节介绍Speex的特性以及一些文档中用到的基本术语。第4节是关于Speex提供的标准命令行工具。第5节是使用libspeex API进行编程的详细说明。第7节是一些关于Speex相关标准的信息。</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;&nbsp;&nbsp; The three last sections describe the algorithms used in Speex. These sections require signal processing knowledge, but are not required for merely using Speex. They are intended for people who want to understand how Speex really works and/or want to do research based on Speex. Section 8 explains the general idea behind CELP, while sections 9 and 10 are specific to Speex.</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">&nbsp;&nbsp;&nbsp; 最后三节介绍了Speex使用的算法。这部分需要信号处理相关知识，但这是对于那些想了解Speex的真正工作原理或基于Speex进行研究的人，如果仅仅是使用Speex库则不是必需的。第8节大概介绍了CELP（码激励线性预测）编码，9和10节是关于Speex的一些具体介绍。</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">后记：</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">如果哪位同学已拥有此手册的中文版本，可留我一份，不然偶得继续增强英文了，也不算一件坏事。</p></div></div><img src ="http://www.cppblog.com/tx7do/aggbug/195511.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-21 23:59 <a href="http://www.cppblog.com/tx7do/archive/2012/11/21/195511.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Speex manul中文版</title><link>http://www.cppblog.com/tx7do/archive/2012/11/21/195510.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Wed, 21 Nov 2012 15:56:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/21/195510.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195510.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/21/195510.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195510.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195510.html</trackback:ping><description><![CDATA[<strong style="color: red">转载自:</strong><a style="color: red" href="http://www.cnblogs.com/rosesmall/archive/2012/04/18/2455395.html"><strong>http://www.cnblogs.com/rosesmall/archive/2012/04/18/2455395.html</strong></a><br /><br />
<div style="widows: 2; text-transform: none; text-indent: 0px; font: 13px/19px Verdana, Geneva, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-break: normal !important; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" id="cnblogs_post_body">
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span><strong>在VOIP的音频算法中，回音处理已经成为一个关系通话质量的主要问题。</strong></span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span><strong>回声的产生在IP网络主要有两种：<br />1.声学回声<br />2.电路回声</strong></span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span><strong>声学回声主要又分成以下几种:<br />a ) 直接回声:由扬声器产生的声音未经任何反射直接进入麦克风<br />b ) 间接回声: 由扬声器发出的声音经过多次反射后,再进入Mic<br />对于第二种回声,拥有多路径,时变性的特点.是比较难处理的.</strong></span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span><strong>由于IP网络下的传输的延迟较大,而一般情况下,对于人耳,如果声音延迟达到了10ms以上的话,那么回声就会越来越明显.<br />一般来讲,VOIP中的声音延迟主要来自于几个方面:<br />1. 编码延迟: 一般情况下编码算法在声音压缩时都会产生延迟,就我们采用的Speex来讲,延迟大概在20ms左右<br />2. 处理延迟, 封装时延, 缓冲时延等<br />3. 在IP网络中数据的传输过程也会照成延时.这由当前的网络状况决定.</strong></span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span><strong>回声消除的模型:<br />a) 建立远端声音模型,进行回声估计, 从采集的值中减去估计值<br />b) 声学模型</strong></span></span></p>
<h4 id="subjcns!31B2F8637FF39314!234" class="TextColor1"><span>Speex manul(手册)中文版</span></h4>
<div id="msgcns!31B2F8637FF39314!234">
<div>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span>Speex</span></span><span>是一套专门用于压缩声音的库</span><span lang="EN-US"><span>,</span></span><span>由于其专门针对声音</span><span lang="EN-US"><span>,</span></span><span>所以压缩声音的性能非常高</span><span lang="EN-US"><span>.Speex</span></span><span>由于其压缩性能</span><span lang="EN-US"><span>,</span></span><span>及</span><span lang="EN-US"><span>0.80</span></span><span>版后的跨平台的性能</span><span lang="EN-US"><span>,</span></span><span>所以在网络声音的传输中有很大的价值</span><span lang="EN-US"><span>.</span></span><span>但是需要注意的是</span><span lang="EN-US"><span>speex</span></span><span>只能对声音进行压缩</span><span lang="EN-US"><span>,</span></span><span>不支持音乐的压缩</span><span lang="EN-US"><span>,</span></span><span>如果你需要音乐的压缩你或许需要用</span><span lang="EN-US"><span>vorbis</span></span><span>库</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span>但是的</span><span lang="EN-US"><span>speex</span></span><span>资料像其它大都数专用库一样</span><span lang="EN-US"><span>,</span></span><span>并没有大多的中文资料</span><span lang="EN-US"><span>.</span></span><span>所以在这里我决定将里面最核心的编程技术翻译出来</span><span lang="EN-US"><span>.</span></span><span>一来是练习练习自己翻译资料的能力</span><span lang="EN-US"><span>,</span></span><span>二来是方便一些英语水平较差的朋友</span><span lang="EN-US"><span>.</span></span><span>由于本人能力有限</span><span lang="EN-US"><span>,</span></span><span>有些感觉有出入或难理解的地方可以去</span><span lang="EN-US"><span>speex</span></span><span>的官方网站</span><span lang="EN-US"><a style="background-color: transparent; color: rgb(51,102,153); text-decoration: none; background-origin: initial; background-clip: initial" href="http://www.speex.org/"><span>www.speex.org</span></a></span><span>找到英文原版的说明</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span>翻译的一些说明</span><span lang="EN-US"><span>:</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span>1,</span></span><span>对于一些专有名词如</span><span lang="EN-US"><span>speex,api</span></span><span>不过行翻译</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span>2,</span></span><span>对于一些新概念翻译</span><span lang="EN-US"><span>,</span></span><span>以及其它的翻译过来也许会产生歧义的文字</span><span lang="EN-US"><span>,</span></span><span>用中</span><span lang="EN-US"><span>/</span></span><span>英两种方式标出</span><span lang="EN-US"><span>:</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span>如</span><span lang="EN-US"><span>:</span></span><span>对话</span><span lang="EN-US"><span>(speech),</span></span><span>位采集</span><span lang="EN-US"><span>(bit_packing)</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span>3,</span></span><span>基本做到和英文原行对译</span><span lang="EN-US"><span>.</span></span><span>及英文原文一行</span><span lang="EN-US"><span>,</span></span><span>中文翻译过来也是一行</span><span lang="EN-US"><span>,</span></span><span>使翻译后的文章和原文基本行行对照</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span>4,</span></span><span>源代码不翻译</span><span lang="EN-US"><span>,</span></span><span>如</span><span lang="EN-US"><span>SpeexBits bits;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span>5,</span></span><span>语言中的关健字不译</span><span lang="EN-US"><span>,</span></span><span>如</span><span lang="EN-US"><span>float</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span>6,</span></span><span>一此不是关健字但英文通常出现的词第一次以中</span><span lang="EN-US"><span>/</span></span><span>英文格式给出</span><span lang="EN-US"><span>,</span></span><span>之后按具体情况给出英文或中文</span><span lang="EN-US"><span>,</span></span><span>如</span><span lang="EN-US"><span>:frame(</span></span><span>帧</span><span lang="EN-US"><span>),</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span lang="EN-US"><span>7,</span></span><span>对一些有自己翻译起来感觉有歧义的地方</span><span lang="EN-US"><span>,</span></span><span>加斜线作标记</span>&nbsp;</p></div></div>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span><strong>1,speex的介绍(略)</strong></span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span><strong><span>2</span>特征描述</strong></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>这个章节展示了</span><span lang="EN-US"><span>speex</span></span><span>的主要特征</span><span lang="EN-US"><span>,</span></span><span>以衣一些关于对话</span><span lang="EN-US"><span>(speech)</span></span><span>编码的一个概念</span><span lang="EN-US"><span>,</span></span><span>以便</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>帮助我们更好的了解下一章节</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span><strong>取样率<span>(Sampling rate)</span></strong></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>Speex</span></span><span>主要是设计了三种不同的取样率</span><span lang="EN-US"><span>:8kHz,16kHz,32kHz.</span></span><span>这些分别代表了窄宽</span><span lang="EN-US"><span>(narrowband),</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>多频率</span><span lang="EN-US"><span>,</span></span><span>超声</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span><strong>质量</strong></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>Speex</span></span><span>编码大都数时间是被一个范围为</span><span lang="EN-US"><span>0</span></span><span>到</span><span lang="EN-US"><span>10</span></span><span>的质量参数来控制</span><span lang="EN-US"><span>&nbsp;&nbsp;</span></span><span>的</span><span lang="EN-US"><span>.</span></span><span>在一个比特率为常量</span><span lang="EN-US"><span>(CBR)</span></span><span>的操作中</span><span lang="EN-US"><span>,</span></span><span>质量参数是一个整数</span><span lang="EN-US"><span>,</span></span><span>而对于变动的比特率</span><span lang="EN-US"><span>(VBR)</span></span><span>参数是一个</span><span lang="EN-US"><span>float;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span><strong><span>复杂性</span><span lang="EN-US"><span>(</span></span><span>变量</span><span lang="EN-US"><span>)</span></span></strong></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>用</span><span lang="EN-US"><span>speex,</span></span><span>你可以将编码设置成允许的复杂度</span><span lang="EN-US"><span>.</span></span><span>这由一个范围为</span><span lang="EN-US"><span>1</span></span><span>到</span><span lang="EN-US"><span>10</span></span><span>的整数来控制完成</span><span lang="EN-US"><span>,</span></span><span>就像你用选项</span><span lang="EN-US"><span>-1</span></span><span>到</span><span lang="EN-US"><span>-9</span></span><span>来控制</span><span lang="EN-US"><span>gzip</span></span><span>和</span><span lang="EN-US"><span>bzip2</span></span><span>的压缩质量</span><span lang="EN-US"><span>.</span></span><span>在通常的运用中</span><span lang="EN-US"><span>,</span></span><span>噪声级别的复杂度</span><span lang="EN-US"><span>1</span></span><span>是在</span><span lang="EN-US"><span>1</span></span><span>到</span><span lang="EN-US"><span>2dB</span></span><span>之间</span><span lang="EN-US"><span>,</span></span><span>比复杂度</span><span lang="EN-US"><span>10</span></span><span>要高</span><span lang="EN-US"><span>,</span></span><span>但是</span><span lang="EN-US"><span>CPU</span></span><span>需要复杂度</span><span lang="EN-US"><span>10</span></span><span>大概</span><span lang="EN-US"><span>5</span></span><span>倍高行复杂度</span><span lang="EN-US"><span>1.</span></span><span>在实践中</span><span lang="EN-US"><span>,</span></span><span>最好的是设置在</span><span lang="EN-US"><span>2</span></span><span>到</span><span lang="EN-US"><span>4</span></span><span>之间</span><span lang="EN-US"><span>,</span></span><span>尽管更高的设定通常有用</span><span lang="EN-US"><span>,</span></span><span>当编码一个非对话声音</span><span lang="EN-US"><span>(non-speech sounds)</span></span><span>像</span><span lang="EN-US"><span>DTMF</span></span><span>语调</span><span lang="EN-US"><span>(tones).</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span><strong>变波特率<span>(VBR</span></strong></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>Variable bit-rate (VBR) allows a codec to change its bit-rate dynamically to adapt to</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>变波特率</span><span lang="EN-US"><span>(VBR)</span></span><span>允许编码动态地改变它的波特率以适应声音编码的</span><span lang="EN-US"><span>&#8221;</span></span><span>难度</span><span lang="EN-US"><span>&#8221;.</span></span><span>在</span><span lang="EN-US"><span>speex</span></span><span>举例来说</span><span lang="EN-US"><span>,</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>像元音</span><span lang="EN-US"><span>(vowel)</span></span><span>和瞬间高音</span><span lang="EN-US"><span>(high-enenrg transients)</span></span><span>需要个高的比特率来</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>取得一个不错的质量</span><span lang="EN-US"><span>,</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>而摩擦音</span><span lang="EN-US"><span>(fricative)</span></span><span>可以被充分地用相对较少的字节来进行编码</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>由于上面这个原因</span><span lang="EN-US"><span>,VBR</span></span><span>可以调节到一个低的比特率却达到一个同样的质量</span><span lang="EN-US"><span>,</span></span><span>或者用</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>某个比特率达到更好的质量</span><span lang="EN-US"><span>.</span></span><span>尽管有上面这些优点</span><span lang="EN-US"><span>,</span></span><span>但是</span><span lang="EN-US"><span>VBR</span></span><span>也有两个主要的缺点</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>首先</span><span lang="EN-US"><span>,</span></span><span>仅仅靠指定质量值</span><span lang="EN-US"><span>,</span></span><span>这里没有一个关于最后平均比特率的保证</span><span lang="EN-US"><span>.(</span></span><span>译者注</span><span lang="EN-US"><span>:</span></span><span>作者大概是想说没有什么明确的方法知道质量值</span><span lang="EN-US"><span>)</span></span><span>此外</span><span lang="EN-US"><span>,</span></span><span>对一些即时</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>通信</span><span lang="EN-US"><span>,</span></span><span>像</span><span lang="EN-US"><span>IP</span></span><span>电话</span><span lang="EN-US"><span>(VoIP)</span></span><span>这种包含着最大的比特率的</span><span lang="EN-US"><span>,</span></span><span>必须把比特率设为足够低以适应</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>传输通道</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>r</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span><strong>平均比特率<span>(ABR)</span></strong></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>平均比特率通过动态地调节</span><span lang="EN-US"><span>VBR</span></span><span>质量去得到一个确定的目标的比特率</span><span lang="EN-US"><span>,</span></span><span>从而解决了</span><span lang="EN-US"><span>VBR</span></span><span>中的一个问题</span><span lang="EN-US"><span>..</span></span><span>因为质量</span><span lang="EN-US"><span>/</span></span><span>比特率被即时的调整了</span><span lang="EN-US"><span>,</span></span><span>整体质量将会稍稍低于由</span><span lang="EN-US"><span>VBR</span></span><span>对一个</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>设置得和目标平均比特率非常接近的质量数编码得到的结果</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>&nbsp;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span><strong>声音生动性检测<span>(VAD)</span></strong></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>声音生动性检测将会发觉音频正在被编码成对话</span><span lang="EN-US"><span>,</span></span><span>静音</span><span lang="EN-US"><span>,</span></span><span>或背景噪音</span><span lang="EN-US"><span>.VAD</span></span><span>总在用</span><span lang="EN-US"><span>VBR</span></span><span>进行编码时暗中起作用</span><span lang="EN-US"><span>,</span></span><span>因此选项仅仅对一个不是</span><span lang="EN-US"><span>VBR</span></span><span>的操作起作用</span><span lang="EN-US"><span>.</span></span><span>对于不是</span><span lang="EN-US"><span>VBR</span></span><span>的操作来说</span><span lang="EN-US"><span>,speex</span></span><span>察觉出一个不属于对话的周期</span><span lang="EN-US"><span>,</span></span><span>然后对它用足够的字节重新生成为背景噪音</span><span lang="EN-US"><span>.</span></span><span>不这叫做<span>舒适的噪音生成</span></span><span lang="EN-US"><span>(</span></span><span lang="EN-US"><span>CNG).</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span><strong>不连续传输<span>(DTX)</span></strong></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>不连续传输是</span><span lang="EN-US"><span>VAD/VBR</span></span><span>操作的一个额外选项</span><span lang="EN-US"><span>,</span></span><span>当背景噪音一定时</span><span lang="EN-US"><span>,</span></span><span>它可以完整地传输</span><span lang="EN-US"><span>.</span></span><span>因为在基于文件的操作中</span><span lang="EN-US"><span>,</span></span><span>我们不能停止对文件进行写入</span><span lang="EN-US"><span>,</span></span><span>所以只有</span><span lang="EN-US"><span>5</span></span><span>字节被这种帧所运用</span><span lang="EN-US"><span>.(</span></span><span>给</span><span lang="EN-US"><span>250bps</span></span><span>通信</span><span lang="EN-US"><span>)</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span><strong>Perceptual enhancement</strong></span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span><strong><span>知觉增强</span></strong></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>知觉增加是解码的一部分</span><span lang="EN-US"><span>,</span></span><span>它在打开的时候用来减少由编码解码所产生的噪音</span><span lang="EN-US"><span>.</span></span><span>在大都数</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>情况下</span><span lang="EN-US"><span>,</span></span><span>知觉增强在客观上使声音离原始值更远</span><span lang="EN-US"><span>(</span></span><span>如果用</span><span lang="EN-US"><span>SNR),</span></span><span>但是在最后它仍然听起来更好</span><span lang="EN-US"><span>(</span></span><span>主观上的改进</span><span lang="EN-US"><span>)</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span><strong>Algorithmic delay</strong></span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span><strong>迟时算法</strong></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>每一个声音编码导致了在传输上的延时</span><span lang="EN-US"><span>.</span></span><span>对于</span><span lang="EN-US"><span>speex,</span></span><span>这种延时等于</span><span lang="EN-US"><span>frame</span></span><span>的大小加上一些</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>数量的需要对每一帧进行的前瞻</span><span lang="EN-US"><span>(&#8221;look-adhead&#8221;).</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>在窄宽操作中</span><span lang="EN-US"><span>(8kHz),</span></span><span>迟时是</span><span lang="EN-US"><span>30ms,</span></span><span>而对于多频率</span><span lang="EN-US"><span>(2-44Hz),</span></span><span>迟时是</span><span lang="EN-US"><span>34ms.</span></span><span>这些值</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>不包括</span><span lang="EN-US"><span>CPU</span></span><span>编码</span><span lang="EN-US"><span>,</span></span><span>解码帧的时间</span><span lang="EN-US"><span>.</span></span>&nbsp;</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span><strong>用<span>speex</span>编程<span>(the libspeex api)</span></strong></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>这个章节出要讲述了如何用</span><span lang="EN-US"><span>speex api</span></span><span>进行编程</span><span lang="EN-US"><span>.</span></span><span>例子的源代友你也可以在附录</span><span lang="EN-US"><span>B</span></span><span>中找到</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span><strong>4.1 Encoding</strong></span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span><strong><span>4.1</span>压缩</strong></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>为了用</span><span lang="EN-US"><span>Speex</span></span><span>压缩对话</span><span lang="EN-US"><span>,</span></span><span>你首先需要引用头文件</span><span lang="EN-US"><span>:</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>#include &lt;speex.h&gt;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>然后你需要定义一个</span><span lang="EN-US"><span>Speex</span></span><span>的位采集</span><span lang="EN-US"><span>(bit-packing)</span></span><span>结构</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>SpeexBits bits;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>and a Speex encoder state</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>以及定义一个</span><span lang="EN-US"><span>speex</span></span><span>编码器状态量</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>void *enc_state;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>上面定义的这样被初始化</span><span lang="EN-US"><span>:</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>The two are initialized by:</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>speex_bits_init(&amp;bits);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>enc_state = speex_encoder_init(&amp;speex_nb_mode);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>为了支持多频率的压缩</span><span lang="EN-US"><span>,speex_nb_mode</span></span><span>将被</span><span lang="EN-US"><span>sppex_wb_mode</span></span><span>取代</span><span lang="EN-US"><span>.</span></span><span>在大都数</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>情况下</span><span lang="EN-US"><span>,</span></span><span>你需要知道你用的模式</span><span lang="EN-US"><span>(mode)</span></span><span>的帧</span><span lang="EN-US"><span>(frame)</span></span><span>的大小</span><span lang="EN-US"><span>,</span></span><span>你可以得到在</span><span lang="EN-US"><span>frame_size</span></span><span>变量里得到这值</span><span lang="EN-US"><span>:</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>speex_encoder_ctl(enc_state,SPEEX_GET_FRAME_SIZE,&amp;frame_size);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>一但初始化完毕</span><span lang="EN-US"><span>,</span></span><span>对于每一个输入帧</span><span lang="EN-US"><span>:</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>speex_bits_reset(&amp;bits);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>speex_encode(enc_state, input_frame, &amp;bits);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>nbBytes = speex_bits_write(&amp;bits, byte_ptr, MAX_NB_BYTES);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>上面</span><span lang="EN-US"><span>input_frame</span></span><span>是一个指向对话</span><span lang="EN-US"><span>(speech)</span></span><span>帧</span><span lang="EN-US"><span>(frame)</span></span><span>的</span><span lang="EN-US"><span>float</span></span><span>指针</span><span lang="EN-US"><span>(pointing);byte_ptr</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>是指向编码帧开始写的地方的</span><span lang="EN-US"><span>char</span></span><span>指针</span><span lang="EN-US"><span>,MAX_NB_BYTES</span></span><span>是能</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>写进</span><span lang="EN-US"><span>byte_ptr</span></span><span>而不会造成溢出的最大数</span><span lang="EN-US"><span>.nbBytes</span></span><span>是一个实际写入</span><span lang="EN-US"><span>btye_ptr</span></span><span>的数</span><span lang="EN-US"><span>,</span></span><span>即编码的实际大小</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>在调用</span><span lang="EN-US"><span>speex_bits_write</span></span><span>前</span><span lang="EN-US"><span>,</span></span><span>可能你需要调用</span><span lang="EN-US"><span>speex_bits_nbytes(&amp;bits)</span></span><span>得到需要写入</span><span lang="EN-US"><span>(write)</span></span><span>的字节大小</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>在你已经编码后</span><span lang="EN-US"><span>,</span></span><span>释放所有的资源</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>speex_bits_destroy(&amp;bits);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>speex_encoder_destroy(enc_state);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>That&#8217;s about it for the encoder.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>&nbsp;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>这就是关于编码的方面</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span>&nbsp;</span></p>
<h4 id="subjcns!31B2F8637FF39314!276" class="TextColor1"><span>Speex manul中文版三</span></h4>
<div id="msgcns!31B2F8637FF39314!276">
<div>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>附源代码的翻译</span><span lang="EN-US"><span>:</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span><strong>B Sample code</strong></span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span><strong><span>B&nbsp;</span>例程源代码</strong></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>这个章节演示了一段用</span><span lang="EN-US"><span>speex</span></span><span>编码</span><span lang="EN-US"><span>,</span></span><span>解码对话</span><span lang="EN-US"><span>(speech)</span></span><span>的源代码</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>可以如下用</span><span lang="EN-US"><span>api</span></span><span>命令来编码并解码一个文件</span><span lang="EN-US"><span>:</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>译者注</span><span lang="EN-US"><span>:</span></span><span>这里说的</span><span lang="EN-US"><span>api</span></span><span>命令是指</span><span lang="EN-US"><span>unix</span></span><span>的用</span><span lang="EN-US"><span>&#8221;|&#8221;</span></span><span>进行管道写入读出</span><span lang="EN-US"><span>.</span></span><span>在</span><span lang="EN-US"><span>windows</span></span><span>下这样并不能实现</span><span lang="EN-US"><span>.</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>% sampleenc in_file.sw | sampledec out_file.sw</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>这里这两段代码都没有引用其它的头文件</span><span lang="EN-US"><span>,</span></span><span>并以</span><span lang="EN-US"><span>16&nbsp;</span></span><span>比特率</span><span lang="EN-US"><span>(bits)</span></span><span>进行编码</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>natural endianness).</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span><strong>B.1 sampleenc.c</strong></span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>Sameleenc&nbsp;</span></span><span>用一个未加工的</span><span lang="EN-US"><span>16</span></span><span>比特率</span><span lang="EN-US"><span>(bits)</span></span><span>文章</span><span lang="EN-US"><span>,</span></span><span>给它编码并产生一个</span><span lang="EN-US"><span>speex&nbsp;</span></span><span>流</span><span lang="EN-US"><span>(steam)</span></span><span>给标准输出</span><span lang="EN-US"><span>.</span></span><span>注意已压缩的和</span><span lang="EN-US"><span>speexenc/speexdec</span></span><span>不和谐</span><span lang="EN-US"><span>!</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>#include &lt;speex.h&gt;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>#include &lt;stdio.h&gt;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>/*</span></span><span>帧的大小在这个例程中是一个固定的值</span><span lang="EN-US"><span>,</span></span><span>但它并不是必须这样</span><span lang="EN-US"><span>*/</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>&nbsp;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>#define FRAME_SIZE 160</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>int main(int argc, char **argv)</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>{</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>char *inFile;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>FILE *fin;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>short in[FRAME_SIZE];</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>float input[FRAME_SIZE];</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>char cbits[200];</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>int nbBytes;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>/*</span></span><span>保存编码的状态</span><span lang="EN-US"><span>*/</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>void *state;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>/*</span></span><span>保存字节因此他们可以被</span><span lang="EN-US"><span>speex</span></span><span>常规</span><span>读写</span><span lang="EN-US"><span>*/</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>&nbsp;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>SpeexBits bits;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>int i, tmp;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>//</span></span><span>新建一个新的编码状态在窄宽</span><span lang="EN-US"><span>(narrowband)</span></span><span>模式下</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>state = speex_encoder_init(&amp;speex_nb_mode);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>//</span></span><span>设置质量为</span><span lang="EN-US"><span>8(15kbps)</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>tmp=8;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>speex_encoder_ctl(state, SPEEX_SET_QUALITY, &amp;tmp);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>inFile = argv[1];</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>fin = fopen(inFile, "r");</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>//</span></span><span>初始化结构使他们保存数据</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>speex_bits_init(&amp;bits);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>while (1)</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>{</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>//</span></span><span>读入一帧</span><span lang="EN-US"><span>16bits</span></span><span>的声音</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>fread(in, sizeof(short), FRAME_SIZE, fin);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>if (feof(fin))</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>break;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>//</span></span><span>把</span><span lang="EN-US"><span>16bits</span></span><span>的值转化为</span><span lang="EN-US"><span>float,</span></span><span>以便</span><span lang="EN-US"><span>speex</span></span><span>库可以在上面工作</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>for (i=0;i&lt;FRAME_SIZE;i++)</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>input[i]=in[i];</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>//</span></span><span>清空这个结构体里所有的字节</span><span lang="EN-US"><span>,</span></span><span>以便我们可以编码一个新的帧</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>speex_bits_reset(&amp;bits);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>//</span></span><span>对帧进行编码</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>speex_encode(state, input, &amp;bits);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>//</span></span><span>把</span><span lang="EN-US"><span>bits</span></span><span>拷贝到一个利用写出的</span><span lang="EN-US"><span>char</span></span><span>型数组</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>nbBytes = speex_bits_write(&amp;bits, cbits, 200);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>//</span></span><span>首先写出帧的大小</span><span lang="EN-US"><span>,</span></span><span>这是</span><span lang="EN-US"><span>sampledec</span></span><span>文件需要的一个值</span><span lang="EN-US"><span>,</span></span><span>但是你的应用程序中可能不一样</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>fwrite(&amp;nbBytes, sizeof(int), 1, stdout);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>//</span></span><span>写出压缩后的数组</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>fwrite(cbits, 1, nbBytes, stdout);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>}</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>//</span></span><span>释放</span><span>编码器状态量</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>speex_encoder_destroy(state);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>//</span></span><span>释放</span><span lang="EN-US"><span>bit_packing</span></span><span>结构</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>speex_bits_destroy(&amp;bits);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>fclose(fin);</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>return 0;</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span lang="EN-US"><span>}</span></span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px" align="left"><span>&nbsp;</span></p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px"><span>&nbsp;</span></p></div></div>
<div class="postTitle"><a style="background-color: transparent; color: rgb(51,102,153); text-decoration: none; background-origin: initial; background-clip: initial" href="http://blog.donews.com/keo321/archive/2006/12/28/1104088.aspx"><span>如何使用Speex中的AEC模块，提高声音质量？</span></a></div>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">在Speex（<a style="background-color: transparent; color: rgb(51,102,153); text-decoration: none; background-origin: initial; background-clip: initial" href="http://www.speex.org/"><span>www.speex.org</span></a>）的最新版本中，开始集成了回音消除的模块，而回音消除一直是Voip之中亟待解决的主要问题。<br />很多朋友和我说speex的aec模块的效能并不好，我们先来看一下speex的aec的api调用方式。</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">/*<br />*创建AEC对象<br />*/<br />SpeexEchoState *echo_state = speex_echo_state_init(frame_size, filter_length);</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">frame_size 的取值最好是一个编码的frame大小， 在低带宽条件下，一般延迟20ms，而大小为160<br />filter_length,最好是房间内反射时间的1/3<br />如: 一个房间的反射时延为300ms<br />&nbsp;&nbsp;&nbsp; 那么这个filter_length就最好是100ms(这个长度又被称为tail length).</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">而其中filter_length的设定是一个关键。</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">/*<br />*执行AEC<br />*/<br />speex_echo_cancel(echo_state, input_frame, echo_frame, output_frame, residue);</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">其中:<br />input_frame: 就是被声卡捕捉到的声音<br />echo_frame: 是由扬声器播放出的声音,这个声音是需要从 input_frame中抵消的声音.</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">output_frame 是处理完以后输出的声音</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">residue是一个可选参数,如果不使用可以将之设置为NULL, 也可以通过preprocessor 来控制</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">问题的关键是 处理input和echo 之间的关系,<br />也就是说在捕捉到的信号和播放的信号之间的延迟必须足够的小,才可以提高效率.</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">writetosndcard(echo_frame, frame_size)<br />readfromsndcard(input_frame, frame_size)<br />speex_echo_cancel(echo_state, input_frame, echo_frame, output_frame, residue)<br />如果你想要尽可能的减小信号中的回音,那么可以将residue这个参数设置为噪音参数.</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">我相信在大多数情况下，都是因为声音捕捉和声音播放之间的同步问题没有处理好，导致的音频质量下降。</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">/*<br />*销毁和复位<br />*/<br />speex_echo_state_destroy(echo_state);</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">speex_echo_state_reset(echo_state);<br />不再复述了！</p>
<p style="line-height: 1.5; text-indent: 0px; margin: 10px auto; font-size: 13px">说明：<br />据说在Speex的最新的1.2beta版本上，Speex提供了可选择的，简化的API，来提高echo执行过程中的同步问题。</p></div><img src ="http://www.cppblog.com/tx7do/aggbug/195510.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-21 23:56 <a href="http://www.cppblog.com/tx7do/archive/2012/11/21/195510.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Speex 回声消除</title><link>http://www.cppblog.com/tx7do/archive/2012/11/21/195507.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Wed, 21 Nov 2012 15:44:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/21/195507.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195507.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/21/195507.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195507.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195507.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转载自:http://blog.csdn.net/dxpqxb/article/details/7928591为什么需要声学回声消除呢？在一般的VOIP软件或视频会议系统中，假设我们只有A和B两个人在通话，首先，A的声音传给B，B然后用喇叭放出来，而这时B的MIC呢则会采集到喇叭放出来的声音，然后传回给A，如果这个传输的过程中时延足够大，A就会听到一个和自己刚才说过的话一样的声音，这就是回声，...&nbsp;&nbsp;<a href='http://www.cppblog.com/tx7do/archive/2012/11/21/195507.html'>阅读全文</a><img src ="http://www.cppblog.com/tx7do/aggbug/195507.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-21 23:44 <a href="http://www.cppblog.com/tx7do/archive/2012/11/21/195507.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AEC (Acoustic Echo Canceller) 回音消除初探</title><link>http://www.cppblog.com/tx7do/archive/2012/11/21/195505.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Wed, 21 Nov 2012 15:23:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/21/195505.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195505.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/21/195505.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195505.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195505.html</trackback:ping><description><![CDATA[<div><strong style="color: red">转载自:</strong><a style="color: red" href="http://www.cnblogs.com/rainbowzc/archive/2006/08/07/2422323.html"><strong>http://www.cnblogs.com/rainbowzc/archive/2006/08/07/2422323.html</strong></a><br /><br />
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; font: 13px/1.4 Verdana, Geneva, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">AEC回声抑制算法，这个比较难，目前可以使用directsound进行处理，不过只能在xp下使用，别的系统不支持！<br />目前gips对本算法有出色的实现，skype就是使用的该引擎！<br />要想自己实现，恐怕很困难！<br />&nbsp;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; font: 13px/1.4 Verdana, Geneva, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">AEC 模块是 Microsoft DirectSound 底层结构的一部分。该组件包括下列特性和限制：</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; font: 13px/1.4 Verdana, Geneva, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">AEC只在不超过 25&#215;15&#215;9 英尺的小房间才会有效；<span class="Apple-converted-space">&nbsp;</span><br />AEC只对单声道有效，当输出是多个通道的立体声的时候，只有一个通道能够具有回波抵消的效果；<span class="Apple-converted-space">&nbsp;</span><br />AEC不能抵消来自其它声音源的声音，比如背景中收音机放出来的歌曲；<br />IDirectSoundFullDuplex8*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DirectSoundFD;//<br />IDirectSoundCaptureBuffer8*&nbsp; DirectSoundCaptureBuf8;//捕捉缓冲区接口指针<br />IDirectSoundBuffer8*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DirectSoundBuf8;//回放缓冲区接口指针<br />IDirectSoundBuffer8*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pIUnkown;//回放缓冲区接口指针</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; font: 13px/1.4 Verdana, Geneva, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">extern "C" const GUID IID_IDirectSoundBuffer8 = {0x6825a449, 0x7524, 0x4d82,{ 0x92, 0x0f, 0x50, 0xe3, 0x6a, 0xb3, 0xab, 0x1e}};<br />extern "C" const GUID GUID_DSCFX_MS_NS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = {0x11c5c73b, 0x66e9, 0x4ba1, {0xa0, 0xba, 0xe8, 0x14, 0xc6, 0xee, 0xd9, 0x2d}};<br />extern "C" const GUID GUID_DSCFX_CLASS_NS = {0xe07f903f, 0x62fd, 0x4e60, {0x8c, 0xdd, 0xde, 0xa7, 0x23, 0x66, 0x65, 0xb5}};<br />extern "C" const GUID GUID_DSCFX_MS_AEC = {0xcdebb919, 0x379a, 0x488a, {0x87, 0x65, 0xf5, 0x3c, 0xfd, 0x36, 0xde, 0x40}};<br />extern "C" const GUID GUID_DSCFX_CLASS_AEC = {0xBF963D80L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};<br />extern "C" const GUID DAlgorithm ={0x00000000,&nbsp; 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; font: 13px/1.4 Verdana, Geneva, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><br />//1.创建及初始化DirectSound<br />WAVEFORMATEX WaveDataFormat={WAVE_FORMAT_PCM, 1,8000,16000,2,16, 0};&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Apple-converted-space">&nbsp;</span><br />//回放缓冲区。render buffer<br />DSBUFFERDESC desc;<br />memset(&amp;desc, 0, sizeof(desc));<span class="Apple-converted-space">&nbsp;</span><br />desc.dwSize = sizeof(desc);<br />desc.dwFlags = DSBCAPS_CTRLFX | DSBCAPS_GLOBALFOCUS;<br />desc.dwBufferBytes = 2000 * NUM_REC_NOTIFICATIONS;//待定<br />desc.dwReserved = 0;<br />desc.lpwfxFormat = &amp;WaveDataFormat;<br />&nbsp;&nbsp;&nbsp;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; font: 13px/1.4 Verdana, Geneva, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">//捕捉缓冲区AEC和NS效果。<br />DSCEFFECTDESC efft[2];<br />memset(efft, 0, sizeof(efft));<br />//AEC效果<br />efft[0].dwSize = sizeof(efft[0]);<br />efft[0].dwFlags = DSCFX_LOCSOFTWARE;<br />efft[0].guidDSCFXClass = GUID_DSCFX_CLASS_AEC;<br />efft[0].guidDSCFXInstance = GUID_DSCFX_MS_AEC;<br />//NS效果<br />efft[1].dwSize = sizeof(efft[1]);<br />efft[1].dwFlags = DSCFX_LOCSOFTWARE;<br />efft[1].guidDSCFXClass = GUID_DSCFX_CLASS_NS;<br />efft[1].guidDSCFXInstance = GUID_DSCFX_MS_NS;<br />&nbsp;&nbsp;&nbsp;<span class="Apple-converted-space">&nbsp;</span><br />//捕捉缓冲区。capture buffer<br />DSCBUFFERDESC cdesc;<br />memset(&amp;cdesc, 0, sizeof(cdesc));<br />cdesc.dwSize = sizeof(cdesc);<br />cdesc.dwFlags = DSCBCAPS_CTRLFX;<span class="Apple-converted-space">&nbsp;</span><br />cdesc.dwBufferBytes =&nbsp; 2000 * NUM_REC_NOTIFICATIONS;//待定<br />cdesc.lpwfxFormat = &amp;WaveDataFormat;<br />cdesc.dwFXCount = 2;<br />cdesc.lpDSCFXDesc = efft;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; font: 13px/1.4 Verdana, Geneva, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">HWND win = AfxGetApp()-&gt;m_pMainWnd-&gt;m_hWnd;<br />hr = DirectSoundFullDuplexCreate8(0, 0,&amp;cdesc, &amp;desc,win,<span class="Apple-converted-space">&nbsp;</span><br />DSSCL_PRIORITY,&amp;DirectSoundFD, &amp;DirectSoundCaptureBuf8,&amp;DirectSoundBuf8, 0);<span class="Apple-converted-space">&nbsp;</span><br />DXTRACE_ERR( TEXT("DirectSoundFullDuplexCreate8"), hr );<br />//成功创建DirectSoundFD，DirectSoundCaptureBuf8，DirectSoundBuf8，均不为零。</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; font: 13px/1.4 Verdana, Geneva, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">if(!FAILED(hr))<br />&nbsp;&nbsp;&nbsp; DirectSoundFD-&gt;QueryInterface(IID_IDirectSoundBuffer8, (void**)pIUnkown);<br />//发现上面的pIUnkown=0，查询失败，为什么？<br />&nbsp;&nbsp;&nbsp; AfxMessageBox("失败");</p></div><img src ="http://www.cppblog.com/tx7do/aggbug/195505.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-21 23:23 <a href="http://www.cppblog.com/tx7do/archive/2012/11/21/195505.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Silk codec的一些资料</title><link>http://www.cppblog.com/tx7do/archive/2012/11/16/195277.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Fri, 16 Nov 2012 09:18:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/16/195277.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/195277.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/16/195277.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/195277.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/195277.html</trackback:ping><description><![CDATA[<p style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; padding-left: 0px; padding-right: 0px; font: 14px/25px verdana, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><strong style="color: red">转载自:</strong><a style="color: red" href="http://www.cnblogs.com/c6000/archive/2011/03/17/1986609.html"><strong>http://www.cnblogs.com/c6000/archive/2011/03/17/1986609.html</strong></a><br /><br />Skype表示它最近将开始向第三方开发人员和硬件制造商提供免版税认证(RF)的Silk宽带音频编码器。</p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; padding-left: 0px; padding-right: 0px; font: 14px/25px verdana, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Silk下载地址如下</p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; padding-left: 0px; padding-right: 0px; font: 14px/25px verdana, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><a style="border-bottom: rgb(51,51,51) 1px dotted; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(0,0,0); text-decoration: none; padding-top: 0px" href="http://developer.skype.com/silk/SILK_SDK_SRC_v1.0.7.zip">http://developer.skype.com/silk/SILK_SDK_SRC_v1.0.7.zip</a></p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; padding-left: 0px; padding-right: 0px; font: 14px/25px verdana, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Silk标准下载地址如下</p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; padding-left: 0px; padding-right: 0px; font: 14px/25px verdana, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><a style="border-bottom: rgb(51,51,51) 1px dotted; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(0,0,0); text-decoration: none; padding-top: 0px" href="http://tools.ietf.org/html/draft-vos-silk-01">http://tools.ietf.org/html/draft-vos-silk-01</a></p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; padding-left: 0px; padding-right: 0px; font: 14px/25px verdana, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Silk的一些文档</p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; padding-left: 0px; padding-right: 0px; font: 14px/25px verdana, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><a style="border-bottom: rgb(51,51,51) 1px dotted; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(0,0,0); text-decoration: none; padding-top: 0px" href="http://developer.skype.com/silk">http://developer.skype.com/silk</a></p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; padding-left: 0px; padding-right: 0px; font: 14px/25px verdana, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Silk简介</p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; padding-left: 0px; padding-right: 0px; font: 14px/25px verdana, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">SILK最早在Windows版Skype的4.0版本中被披露,它成为了Skype到Skype通话的默认解码器,实时带宽6-40Kbps即可工作,即使丢包水平达到10%依然可以稳定维持24KHz采样的通话音质.</p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; padding-left: 0px; padding-right: 0px; font: 14px/25px verdana, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Arial; padding-top: 0px" face="Arial">Skype投入了数百万美元，耗时三年多开发了Silk，他们表示Silk可以使VoIP通话听起来好像你和对话的人在同一间房子里一样。大部分电话只能传输3.4kHz(码率)的信号，而Silk可以让Skype传输高达12kHz的信号。</span></p>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 10px auto; padding-left: 0px; padding-right: 0px; font: 14px/25px verdana, Arial, Helvetica, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Arial; padding-top: 0px" face="Arial">开放编码器可以被看作是Skype放弃了一项竞争优势，但是它是Skype将其服务推广到更多设备这一长期战略中的一环。该公司已经有4.05亿套软件的装机量，其中绝大部分用户是台式计算机用户。免费提供其编码器可以让设备制造商将Skype整合到像智能电话、手机或移动互联设备中去。</span><span style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Arial; padding-top: 0px" face="Arial">Skype已经开始着手将其服务推广到其它平台上，并发布了基于Android和支持Java手机的通话服务。该公司还和诺基亚合作将其VoIP软件预装到智能手机上，例如N97。</span></p><img src ="http://www.cppblog.com/tx7do/aggbug/195277.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-16 17:18 <a href="http://www.cppblog.com/tx7do/archive/2012/11/16/195277.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>混音器编程接口讨论</title><link>http://www.cppblog.com/tx7do/archive/2012/11/05/194617.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Mon, 05 Nov 2012 10:23:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/11/05/194617.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/194617.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/11/05/194617.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/194617.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/194617.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转载自:http://www.cnblogs.com/windviki/archive/2011/08/31/2160683.html混音器编程接口讨论翻译：windviki@gmail.com&nbsp;转载请注明译自：MIXER API ARGUMENTATION为了理解混音器API是如何工作的，必须先了解典型的声卡的硬件布局。我们有必要想象一下，声卡上有各种独...&nbsp;&nbsp;<a href='http://www.cppblog.com/tx7do/archive/2012/11/05/194617.html'>阅读全文</a><img src ="http://www.cppblog.com/tx7do/aggbug/194617.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-11-05 18:23 <a href="http://www.cppblog.com/tx7do/archive/2012/11/05/194617.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Skype SILK vs. iLBC vs. Speex</title><link>http://www.cppblog.com/tx7do/archive/2012/10/24/193779.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Wed, 24 Oct 2012 07:06:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/10/24/193779.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/193779.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/10/24/193779.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/193779.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/193779.html</trackback:ping><description><![CDATA[<div><strong style="color: red">转载自:</strong><a style="color: red" href="http://blog.csdn.net/wanggp_2007/article/details/5540686"><strong>http://blog.csdn.net/wanggp_2007/article/details/5540686</strong></a><br /><br />
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">对比一下这三种VOIP语音算法的特点:</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">1 参数与特征</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="" src="http://hi.csdn.net/attachment/201004/28/0_12724708406VXX.gif" /></p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">2 SILK性能</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="" src="http://hi.csdn.net/attachment/201004/28/0_1272469009ldFP.gif" /></p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; border-image: initial" alt="" src="http://hi.csdn.net/attachment/201004/28/0_1272469047QpEs.gif" /></p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 关于iLBC和Speex的性能可以参考以前写的文章。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">3 关于VOIP一些观点（仅代表个人观点）</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;1)&nbsp;&nbsp;Skype 辛苦三年开发的SILK为什么要开源？</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; &nbsp; &nbsp; 第一，技术上，其实SILK用到了很多Royalty Free的算法部分，遵循开源的法则，取之于民，用之于民；</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; &nbsp; &nbsp; 第二，商业上，Skype 根本不靠Codec赚钱，他本身最大的优势是网络条件做的比较好，这种环境下无论是SILK、iLBC还是G.729都可以达成比较不错的音质。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; &nbsp; &nbsp; 第三，口碑上，提高知名度，都已经把SILK定点好了，将来一定会有很多第三方去推广，广告、市场和口碑双赢；</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 2）iLBC一定就比Speex质量好吗？</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; &nbsp; &nbsp; 根据目前的评测，当二者的编码速率差不多时，iLBC的质量要好于Speex，但是也有一些牛人认为iLBC这种每帧独立编码的思想其实是低效率的，通过增加编码冗余也可以达到相同的音质，意思是将CELP编码器增加一些前后冗余信息适当提高码率，也可以提高丢包情况下的抗干扰性，这个暂时还没有定论。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 3）Speex 总感觉用的人少？</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; &nbsp;到底是Speex的推广差、维护差，还是音质差？虽然Speex的开发者出来解释了很多原因，可是目前好像用的第三方不是很多，同时我也感觉它的音质好像是有一点差。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 4）有了SILK，还有人用iLBC吗？</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; &nbsp;SILK和iLBC来自两个不同公司skype and GIPS，个人感觉会同时存在。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">好了，欢迎大家对以上观点进行补充，谢谢！</p><br class="Apple-interchange-newline" /></div><img src ="http://www.cppblog.com/tx7do/aggbug/193779.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-10-24 15:06 <a href="http://www.cppblog.com/tx7do/archive/2012/10/24/193779.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google开源实时通信项目WebRTC</title><link>http://www.cppblog.com/tx7do/archive/2012/10/24/193776.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Wed, 24 Oct 2012 06:26:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/10/24/193776.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/193776.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/10/24/193776.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/193776.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/193776.html</trackback:ping><description><![CDATA[<div><strong style="color: red">转载自:</strong><a style="color: red" href="http://www.infoq.com/cn/news/2011/06/google-webrtc"><strong>http://www.infoq.com/cn/news/2011/06/google-webrtc</strong></a><br /><br />
<div style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/19px Lucida, 'Lucida Grande', Tahoma, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" id="newsContent">
<p>最近，Google正式开源了<a style="color: rgb(11,89,178); text-decoration: underline" href="http://sites.google.com/site/webrtc/home">WebRTC实时通信项目</a>，希望浏览器厂商能够将该技术内建在浏览器中，从而使Web应用开发人员能够通过HTML标签和JavaScript API就实现Web音频、视频通信功能。</p>
<p>WebRTC（Web Real Time Communication）并不是Google原来自己的技术。在2010年，Google以大约6820万美元<a style="color: rgb(11,89,178); text-decoration: underline" href="http://www.computerworld.com/s/article/9176906/Google_to_acquire_voice_and_video_codec_company">收购</a>了VoIP软件开发商Global IP Solutions公司，并因此获得了该公司拥有的WebRTC技术。如今，互联网的音频、视频通信服务技术一般都是私有技术，如<a style="color: rgb(11,89,178); text-decoration: underline" href="http://www.skype.com/">Skype</a>， 需要通过安装插件或者桌面客户端来实现通信功能。Google希望Web开发人员能够直接在浏览器中创建视频或语音聊天应用，Global IP Solutions公司之前已经针对Android、Windows Mobile、iPhone制作了基于WebRTC的移动客户端。Google此次将WebRTC开源出来，就是希望浏览器厂商能够将该技术直接内嵌到浏 览器中，从而方便Web开发人员。</p>
<p>WebRTC的<a style="color: rgb(11,89,178); text-decoration: underline" href="http://sites.google.com/site/webrtc/blog">博客</a>说明了WebRTC的优势和发展方向：</p>
<blockquote style="background-image: url(http://cdn2.infoq.com/styles/cn/i/bg-blockquote.gif); border-bottom: rgb(239,239,239) 2px solid; border-left: rgb(239,239,239) 2px solid; padding-bottom: 5px; background-color: rgb(250,250,250); padding-left: 5px; padding-right: 5px; background-position: 5px 5px; color: rgb(51,51,51); margin-left: 20px; border-top: rgb(239,239,239) 2px solid; margin-right: 0px; border-right: rgb(239,239,239) 2px solid; padding-top: 5px; border-image: initial; background-origin: initial; background-clip: initial">
<p style="margin-top: 0px">直到现在，实时通信仍然需要私有的信号处理技术，大部分都是通过插件和客户端来安装使用。我们通过WebRTC开源了收购GIPS后获得的音频、视频引擎技术，让开发人员能够了解信号处理技术，并使用了BSD风格的<a style="color: rgb(11,89,178); text-decoration: underline" href="http://sites.google.com/site/webrtc/license-rights/license">授权</a>。这会支持开发人员通过简单的HTML和JavaScript API创建音频和视频聊天应用。</p>
<p style="margin-bottom: 0px">我们正在与其他浏览器开发厂商Mozilla和Opera等紧密合作，尽快在浏览器中实现这项技术以便于Web社区使用。此外，我们还积极地参与IETF和W3C工作组的活动，定义和实现一套实时通信标准。</p></blockquote>
<p>其<a style="color: rgb(11,89,178); text-decoration: underline" href="http://sites.google.com/site/webrtc/faq">官网</a>上列表了使用WebRTC技术的四个理由：</p>
<ol><li>互联网成功的一个关键因素是一些核心技术如HTML、HTTP和TCP/IP是开放和免费实现的。目前，在浏览器通信领域还没有免费、高质量、完整的解决方案。WebRTC就是这样的技术。</li><li>该技术已经集成了最佳的音频、视频引擎，并被部署到数以百万级的终端中，经过超过8年的磨练。Google不会从该技术中收取费用。</li><li>包含了使用STUN、ICE、TURN、RTP-over-TCP的关键NAT和防火墙穿越技术，并支持代理。</li><li>构建在浏览器中，WebRTC通过提供直接映射到PeerConnection的信号状态机来抽象信号处理。Web开发人员因此可以选择适合应用场景的协议（例如：SIP、XMPP/Jingle等等）。</li></ol>
<p>WebRTC的架构图如下所示：</p>
<p align="center"><img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-image: initial" alt="" src="http://www.infoq.com/resource/news/2011/06/google-webrtc/zh/resources/11.png" _p="true" _href="img://11.png" /></p>
<p align="center">图 1 &nbsp;WebRTC架构图（图片来源：WebRTC官方网站）</p>
<p>关于架构图的组成部分，包括：</p>
<blockquote style="background-image: url(http://cdn2.infoq.com/styles/cn/i/bg-blockquote.gif); border-bottom: rgb(239,239,239) 2px solid; border-left: rgb(239,239,239) 2px solid; padding-bottom: 5px; background-color: rgb(250,250,250); padding-left: 5px; padding-right: 5px; background-position: 5px 5px; color: rgb(51,51,51); margin-left: 20px; border-top: rgb(239,239,239) 2px solid; margin-right: 0px; border-right: rgb(239,239,239) 2px solid; padding-top: 5px; border-image: initial; background-origin: initial; background-clip: initial">Web API&#8212;&#8212;第三方开发人员用来开发基于Web的应用，如视频聊天。<br />WebRTC Native C++ API&#8212;&#8212;浏览器厂商用于实现Web API的函数集。<br />Session Management&#8212;&#8212;抽象session层，支持调用构建和管理层，由应用开发者来决定如何实现协议。<br />VoiceEngine&#8212;&#8212;音频媒体链的框架，从声卡到网络。<br />iSAC&#8212;&#8212;一种用于VoIP和流音频的宽带和超宽带音频编解码器，iSAC采用16 kHz或32 kHz的采样频率和12&#8212;52 kbps的可变比特率。<br />iLBC&#8212;&#8212;用于VoIP和流音频的窄带语音编解码器，使用8 kHZ的采样频率，20毫秒帧比特率为15.2 kbps，30毫米帧的比特率为13.33 kbps，标准由IETF RFC 3951和3952定义。<br />NetEQ for Voice&#8212;&#8212;动态抖动缓存和错误隐藏算法，用于缓解网络抖动和丢包引起的负面影响。在保持高音频质量的同时尽可能降低延迟。<br />VideoEngine&#8212;&#8212;视频媒体链的框架，从相机像头到网络，从网络到屏幕。<br />VP8&#8212;&#8212;来自于WebM项目的视频编解码器，非常适合RTC，因为它是为低延迟而设计开发的。<br />Image enhancements&#8212;&#8212;消除通过摄像头获取的图片的视频噪声等。<br />其他更详细的架构分析可以查看这里的<a style="color: rgb(11,89,178); text-decoration: underline" href="http://sites.google.com/site/webrtc/reference/webrtc-components">文档</a>。</blockquote>
<p>PeerConnection位于WebRTC Native C++ API的最上层，它的代码实现来源于<a style="color: rgb(11,89,178); text-decoration: underline" href="http://code.google.com/apis/talk/libjingle/index.html">libjingle</a>（一款p2p开发工具包），目前被应用于WebRTC中。其中关键的两个类定义是：</p>
<blockquote style="background-image: url(http://cdn2.infoq.com/styles/cn/i/bg-blockquote.gif); border-bottom: rgb(239,239,239) 2px solid; border-left: rgb(239,239,239) 2px solid; padding-bottom: 5px; background-color: rgb(250,250,250); padding-left: 5px; padding-right: 5px; background-position: 5px 5px; color: rgb(51,51,51); margin-left: 20px; border-top: rgb(239,239,239) 2px solid; margin-right: 0px; border-right: rgb(239,239,239) 2px solid; padding-top: 5px; border-image: initial; background-origin: initial; background-clip: initial">class &nbsp;PeerConnectionObserver {<br />public:<br />&nbsp;virtual void OnError();<br />&nbsp;virtual void OnSignalingMessage(const std::string&amp; msg);<br />&nbsp;virtual void OnAddStream(const std::string&amp; stream_id,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int channel_id,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool video);<br />&nbsp;virtual void OnRemoveStream(const std::string&amp; stream_id,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int channel_id,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool video);<br />}; 
<p>该类定义了一个抽象的观察者。开发人员应该继承实现自己的观察者类。</p>class &nbsp;PeerConnection {<br />public:<br />&nbsp;explicit PeerConnection(const std::string&amp; config);<br />&nbsp;bool Initialize();<br />&nbsp;void RegisterObserver(PeerConnectionObserver* observer);<br />&nbsp;bool SignalingMessage(const std::string&amp; msg);<br />&nbsp;bool AddStream(const std::string&amp; stream_id, bool video);<br />&nbsp;bool RemoveStream(const std::string&amp; stream_id);<br />&nbsp;bool Connect();<br />&nbsp;void Close();<br />&nbsp;bool SetAudioDevice(const std::string&amp; wave_in_device,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const std::string&amp; wave_out_device);<br />&nbsp;bool SetLocalVideoRenderer(cricket::VideoRenderer* renderer);<br />&nbsp;bool SetVideoRenderer(const std::string&amp; stream_id,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cricket::VideoRenderer* renderer);<br />&nbsp;bool SetVideoCapture(const std::string&amp; cam_device);<br />};<br />
<p style="margin-bottom: 0px">具体的函数说明可以查看相应的<a style="color: rgb(11,89,178); text-decoration: underline" href="http://sites.google.com/site/webrtc/reference#TOC-PeerConnection-Native-APIs">API介绍</a>。</p></blockquote>
<p>正如Google所说的，它一直在参与制定和实现HTML 5标准中的<a style="color: rgb(11,89,178); text-decoration: underline" href="http://www.whatwg.org/specs/web-apps/current-work/complete/video-conferencing-and-peer-to-peer-communication.html">视频会议和p2p通信部分</a>，虽然还不是正式标准，但是我们可以从草案的示例中看到未来Web开发人员的使用情况：</p>
<blockquote style="background-image: url(http://cdn2.infoq.com/styles/cn/i/bg-blockquote.gif); border-bottom: rgb(239,239,239) 2px solid; border-left: rgb(239,239,239) 2px solid; padding-bottom: 5px; background-color: rgb(250,250,250); padding-left: 5px; padding-right: 5px; background-position: 5px 5px; color: rgb(51,51,51); margin-left: 20px; border-top: rgb(239,239,239) 2px solid; margin-right: 0px; border-right: rgb(239,239,239) 2px solid; padding-top: 5px; border-image: initial; background-origin: initial; background-clip: initial">// the first argument describes the STUN/TURN server configuration<br />var local = new PeerConnection('TURNS example.net', sendSignalingChannel);<br />local.signalingChannel(...); // if we have a message from the other side, pass it along here<br />// (aLocalStream is some GeneratedStream object)<br />local.addStream(aLocalStream); // start sending video<br />function sendSignalingChannel(message) {<br />&nbsp;... // send message to the other side via the signaling channel<br />}<br />function receiveSignalingChannel (message) {<br />&nbsp;// call this whenever we get a message on the signaling channel<br />&nbsp;local.signalingChannel(message);<br />}<br />local.onaddstream = function (event) {<br />&nbsp;// (videoElement is some &lt;video&gt; element)<br />&nbsp;videoElement.src = URL.getObjectURL(event.stream);<br />};<br /></blockquote>
<p>目前有关Web实时通信的技术标准正在制定当中，W3C的<a style="color: rgb(11,89,178); text-decoration: underline" href="http://www.w3.org/2011/04/webrtc-charter.html">Web Real-Time Communication工作组</a>今年五月份刚刚正式成立，并计划在今年第三季度发布第一个公开草案，从其工作组的路线图中可以看出，正式的推荐标准预计将在2013年第一季度发布，有关W3C标准是否会对WebRTC项目的发展有所影响，未来还要看草案的具体细节。</p>
<p>Google希望开源的WebRTC技术能够获得越来越多的浏览器厂商支持，WebRTC的网站已经宣布将在Chrome、Firefox和Opera上实现相应的API接口。Opera首席技术官H&#229;kon Wium Lie对媒体<a style="color: rgb(11,89,178); text-decoration: underline" href="http://www.theregister.co.uk/2011/06/01/google_open_sources_webrtc/">表示</a>，Google能够把价值不菲的代码贡献出来非常了不起，Opera一直希望能够在浏览器中实现实时通信技术。</p>
<p>提到实时通信技术，不得不让人想起行业巨头Skype。巧合的是，就在前不久，微软刚刚斥资85亿美元现金<a style="color: rgb(11,89,178); text-decoration: underline" href="http://news.ifeng.com/gundong/detail_2011_05/11/6302654_0.shtml">收购</a>网络电话服务商Skype，当时有许多分析师指出，<a style="color: rgb(11,89,178); text-decoration: underline" href="http://www.infoq.com/cn/news/2011/05/microsoft-skype">微软的收购将直面Google的竞争</a>：</p>
<blockquote style="background-image: url(http://cdn2.infoq.com/styles/cn/i/bg-blockquote.gif); border-bottom: rgb(239,239,239) 2px solid; border-left: rgb(239,239,239) 2px solid; padding-bottom: 5px; background-color: rgb(250,250,250); padding-left: 5px; padding-right: 5px; background-position: 5px 5px; color: rgb(51,51,51); margin-left: 20px; border-top: rgb(239,239,239) 2px solid; margin-right: 0px; border-right: rgb(239,239,239) 2px solid; padding-top: 5px; border-image: initial; background-origin: initial; background-clip: initial">
<p style="margin-top: 0px">&#8230;...收购也挫败了竞争对手Google利用Skype技术完善通话服务的计划。</p>
<p>MSN即时通讯、必应（bing）搜索、网络广告等成了微软在互联网领域迎战谷歌的三大阵地。然而，相对于谷歌在互联网行业的呼风唤雨，微软的互联网战略一直没有真正展现出让业界看到其能够挑战谷歌的核心优势。</p>
<p>谷歌和苹果都已经在网络电话上投入了数年时间。苹果一直在力推iChat和FaceTime，谷歌也在普及其网络通信相关产品Chat和Voice。不过，谷歌和苹果都有一个共同的问题，他们很难在竞争对手的平台上生存。苹果用户无法和谷歌以及微软的用户进行视频聊天，谷歌在跨 平台方面做了很多努力，但是仍有不少障碍。</p>
<p>不过Skype则没有这一问题，作为免费服务的Skype可以运行在苹果、Linux以及Windows电脑上，也支持Android和iPhone等手机平台，甚至可以在电视机上运行。</p>
<p style="margin-bottom: 0px">收购Skype，微软不仅仅是为了从中受益，微软还希望借此使Skype远离谷歌的&#8220;魔爪&#8221;。如果谷歌收购了Skype，这对微软来说无疑是一个沉重的打击。想想吧，如果谷歌收购了Skype，并将Skype整合进Google Apps、Gmail、Google Talk和Google Voice等谷歌产品之中，再想想如果谷歌将Skype与Android平台进行一些深度整合，这对微软来说，无疑是一场灾难。即便微软并未很好的将Skype整合进自家产品之中，但这也避免了谷歌通过收购Skype来获得巨大的价值。</p></blockquote>
<p>就在微软收购Skype不久，Google就宣布对WebRTC开源，这不免让人有所联想。有国外媒体<a style="color: rgb(11,89,178); text-decoration: underline" href="http://thenextweb.com/google/2011/06/01/google-releases-developer-preview-of-webrtc-its-open-real-time-voice-and-video-platform/">评论</a>说，Google此次开源是想让广大用户远离该行业的领导者如Skype和Apple的FaceTime平台。通过浏览器来支持实时通信技术，Google希望开发社区能够在自己的应用中集成该功能，从而削弱其他对手。</p>
<p>这已经不是Google第一次大方地开源关键项目。去年，Google曾经将VP8视频编解码项目开源，以支持HTML 5技术中的视频媒体播放。如今，多种主流浏览器都已经支持VP8格式，成为主要的多媒体格式，相比伴随着专利、付费纠纷的H.264，开放、免费的VP8更让浏览器厂商放心。</p>
<p>这次WebRTC的开源会对浏览器厂商和实时通信技术领域带来哪些影响，InfoQ中文站将持续关注和及时报道，也欢迎读者朋友发表自己的看法。</p>
<p id="lastElm"></p></div>
<p style="padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); list-style-type: none; margin-top: 5px; text-indent: 0px; padding-left: 0px; padding-right: 0px; font: 12px/19px Lucida, 'Lucida Grande', Tahoma, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(115,115,115); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="miniBio"><strong><a style="padding-bottom: 0px; padding-left: 2px; padding-right: 2px; color: rgb(28,73,123) !important; text-decoration: none; padding-top: 0px" class="editorlink f_taxonomyEditor" href="http://www.infoq.com/cn/author/%E5%B4%94%E5%BA%B7">崔康</a><span class="Apple-converted-space">&nbsp;</span></strong>热情的技术探索者，资深软件工程师，InfoQ编辑，从事企业级Web应用的相关工作，关注性能优化、Web技术、浏览器等领域。</p><br class="Apple-interchange-newline" /></div><img src ="http://www.cppblog.com/tx7do/aggbug/193776.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-10-24 14:26 <a href="http://www.cppblog.com/tx7do/archive/2012/10/24/193776.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>udp丢包 又是udp丢包</title><link>http://www.cppblog.com/tx7do/archive/2012/09/25/191901.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Mon, 24 Sep 2012 19:25:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/09/25/191901.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/191901.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/09/25/191901.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/191901.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/191901.html</trackback:ping><description><![CDATA[<strong style="color: red">转载自:</strong><a style="color: red" href="http://www.cnweblog.com/fly2700/archive/2011/09/19/317825.html"><strong>http://www.cnweblog.com/fly2700/archive/2011/09/19/317825.html</strong></a><br /><br />
<div style="widows: 2; text-transform: none; text-indent: 0px; font: 14px/21px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="postbody">
<p style="margin: 0px 0px 14px">什么会导致udp丢包呢，我这里列举了如下几点原因：</p>
<p style="margin: 0px 0px 14px">1.调用recv方法接收端收到数据后，处理数据花了一些时间，处理完后再次调用recv方法，在这二次调用间隔里,发过来的包可能丢失。对于这种情况可以修改接收端，将包接收后存入一个缓冲区，然后迅速返回继续recv。<br /><br />2.发送的包巨大丢包。虽然send方法会帮你做大包切割成小包发送的事情，但包太大也不行。例如超过30K的一个udp包，不切割直接通过send方法发送也会导致这个包丢失。这种情况需要切割成小包再逐个send。<br /><br />3.发送的包较大，超过mtu size数倍，几个大的udp包可能会超过接收者的缓冲，导致丢包。这种情况可以设置socket接收缓冲。以前遇到过这种问题，我把接收缓冲设置成64K就解决了。<br />int nRecvBuf=32*1024;//设置为32K<br />setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&amp;nRecvBuf,sizeof(int));<br /><br />4.发送的包频率太快，虽然每个包的大小都小于mtu size 但是频率太快，例如40多个mut size的包连续发送中间不sleep，也有可能导致丢包。这种情况也有时可以通过设置socket接收缓冲解决，但有时解决不了。<br /><br />5.发送的广播包或组播包在windws和linux下都接收正常，而arm上接收出现丢包。这个还不好解决，我的解决方法是大包切割成大小为1448的小包发送，每个包之间sleep 1毫秒，虽然笨，但有效。我这里mtu size为1500字节，减去udp包头8个字节，减去传输层几十个字节，实际数据位1448字节。<br />除此之外还可以试试设置arm操作系统缓冲：<br />//设置mtu size 1500最大<br />ifconfig eth0 mtu 1500<br />//查看接收缓冲最大和默认大小。<br />sysctl -A | grep rmem<br />//设置接收缓冲的最大大小<br />sysctl -w net.core.rmem_max=1048576<br />sysctl -w net.core.rmem_default=1048576<br />sysctl -w net.ipv4.udp_mem=1048576<br />sysctl -w net.ipv4.udp_rmem_min=1048576<br /><br />6,局域网内不丢包，公网上丢包。这个问题我也是通过切割小包并sleep发送解决的。如果流量太大，这个办法也不灵了。</p>
<p style="margin: 0px 0px 14px"><br />总之udp丢包总是会有的，如果出现了用我的方法解决不了，还有这个几个方法： 要么减小流量，要么换tcp协议传输，要么做丢包重传的工作</p></div><img src ="http://www.cppblog.com/tx7do/aggbug/191901.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-09-25 03:25 <a href="http://www.cppblog.com/tx7do/archive/2012/09/25/191901.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>糊涂窗口综合症和Nagle算法</title><link>http://www.cppblog.com/tx7do/archive/2012/09/25/191900.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Mon, 24 Sep 2012 19:08:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/09/25/191900.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/191900.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/09/25/191900.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/191900.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/191900.html</trackback:ping><description><![CDATA[<div><strong style="color: red">转载自:</strong><a style="color: red" href="http://www.cnblogs.com/zhaoyl/archive/2012/09/20/2695799.html"><strong>http://www.cnblogs.com/zhaoyl/archive/2012/09/20/2695799.html</strong></a><br /><br />
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; word-break: normal !important; padding-top: 0px" id="cnblogs_post_body">
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">　　前记：TCP/IP详解系列，毕竟不是一本教材，很多地方讲的不细致。比如SWS未说明是什么就开始介绍其避免方法，还和nagle扯在了一起，直觉告诉我二者一定有猫腻，边搜索一下，果然很有收获。今天贴在这里，分享给大家。&nbsp;</strong></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</strong></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">第一部分：SWS</strong></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: 黑体; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><strong style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">何谓糊涂窗口综合症</strong></span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px">　　当发送端应用进程产生数据很慢、或接收端应用进程处理接收缓冲区数据很慢，或二者兼而有之；就会使应用进程间传送的报文段很小，特别是有效载荷很小。 极端情况下，有效载荷可能只有1个字节；而传输开销有40字节(20字节的IP头+20字节的TCP头) 这种现象就叫糊涂窗口综合症。</p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: 黑体; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><strong style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">发送端引起的SWS</strong></span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px">　　如果发送端为产生数据很慢的应用程序服务(典型的有telnet应用)，例如，一次产生一个字节。这个应用程序一次将一个字节的数据写入发送端的TCP的缓存。如果发送端的TCP没有特定的指令，它就产生只包括一个字节数据的报文段。结果有很多41字节的IP数据报就在互连网中传来传去。解决的方法是防止发送端的TCP逐个字节地发送数据。必须强迫发送端的TCP收集数据，然后用一个更大的数据块来发送。发送端的TCP要等待多长时间呢？如果它等待过长，它就会使整个的过程产生较长的时延。如果它的等待时间不够长，它就可能发送较小的报文段，于是，Nagle找到了一个很好的解决方法，发明了Nagle算法。而他选择的等待时间是一个RTT,即下个ACK来到时。</p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: 黑体; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><strong style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">接收端引起的SWS</strong></span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px">　　接收端的TCP可能产生糊涂窗口综合症，如果它为消耗数据很慢的应用程序服务，例如，一次消耗一个字节。假定发送应用程序产生了1000字节的数据块，但接收应用程序每次只吸收1字节的数据。再假定接收端的TCP的输入缓存为4000字节。发送端先发送第一个4000字节的数据。接收端将它存储在其缓存中。现在缓存满了。它通知窗口大小为零，这表示发送端必须停止发送数据。接收应用程序从接收端的TCP的输入缓存中读取第一个字节的数据。在入缓存中现在有了1字节的空间。接收端的TCP宣布其窗口大小为1字节，这表示正渴望等待发送数据的发送端的TCP会把这个宣布当作一个好消息，并发送只包括一个字节数据的报文段。这样的过程一直继续下去。一个字节的数据被消耗掉，然后发送只包含一个字节数据的报文段。</p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px">　　对于这种糊涂窗口综合症，即应用程序消耗数据比到达的慢，有两种建议的解决方法：<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />　　1） Clark解决方法 Clark解决方法是只要有数据到达就发送确认，但宣布的窗口大小为零，直到或者缓存空间已能放入具有最大长度的报文段，或者缓存空间的一半已经空了。<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />　　2 ）延迟确认 第二个解决方法是延迟一段时间后再发送确认。这表示当一个报文段到达时并不立即发送确认。接收端在确认收到的报文段之前一直等待，直到入缓存有足够的空间为止。延迟的确认防止了发送端的TCP滑动其窗口。当发送端的TCP发送完其数据后，它就停下来了。这样就防止了这种症状。迟延的确认还有另一个优点：它减少了通信量。接收端不需要确认每一个报文段。但它也有一个缺点，就是迟延的确认有可能迫使发送端重传其未被确认的报文段。可以用协议来平衡这个优点和缺点，例如现在定义了确认的延迟不能超过500毫秒。</p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: arial; color: rgb(0,0,0); font-size: 13px; padding-top: 0px"><strong style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">第二部分：Nagle算法</strong></span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: arial; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;TCP/IP协议中，无论发送多少数据，总是要在数据前面加上协议头，同时，对方接收到数据，也需要发送ACK表示确认。为了尽可能的利用网络带宽，TCP总是希望尽可能的发送足够大的数据。（一个连接会设置MSS参数，因此，TCP/IP希望每次都能够以MSS尺寸的数据块来发送数据）。</span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">Nagle算法就是为了尽可能发送大块数据，避免网络中充斥着许多小数据块。</span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;<span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(128,0,128); font-size: 13px; padding-top: 0px">N</span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(128,0,128); font-size: 13px; padding-top: 0px">agle算法的基本定义是</span></span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(128,0,128); font-size: 13px; padding-top: 0px"><strong style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">任意时刻，最多只能有一个未被确认的小段</strong><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">。 所谓&#8220;小段&#8221;，指的是小于MSS尺寸的数据块，所谓&#8220;未被确认&#8221;，是指一个数据块发送出去后，没有收到对方发送的ACK确认该数据已收到</span></span></span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(128,0,128); font-size: 13px; padding-top: 0px">。</span><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">&nbsp;&nbsp; &nbsp;<span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">&nbsp;&nbsp; &nbsp;Nagle算法的规则（可参考tcp_output.c文件里tcp_nagle_check函数注释）：</span></span></span></span>&nbsp;</p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">&nbsp;&nbsp; &nbsp; &nbsp;（1）如果包长度达到MSS，则允许发送；</span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">&nbsp;&nbsp; &nbsp; &nbsp;（2）如果该包含有FIN，则允许发送；</span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">&nbsp;&nbsp; &nbsp; &nbsp;（3）设置了TCP_NODELAY选项，则允许发送；</span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">&nbsp;&nbsp; &nbsp; &nbsp;（4）未设置TCP_CORK选项时，若所有发出去的小数据包（包长度小于MSS）均被确认，则允许发送；</span>&nbsp;</p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">&nbsp;&nbsp; &nbsp; &nbsp;（5）上述条件都未满足，但发生了超时（一般为200ms），则立即发送。</span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;<span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(0,0,255); font-size: 13px; padding-top: 0px">Nagle算法只允许一个未被ACK的包存在于网络，它并不管包的大小，因此它事实上就是一个扩展的停-等协议，只不过它是基于包停-等的，而不是基于字节停-等的</span></span></span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(0,0,255); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">。</span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">Nagle算法完全由TCP协议的ACK机制决定，这会带来一些问题，比如如果对端ACK回复很快的话，Nagle事实上不会拼接太多的数据包，虽然避免了网络拥塞，网络总体的利用率依然很低。<span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(0,0,0); font-size: 13px; padding-top: 0px">另外，他是一个自适应的方法，读者可以自己按上述规则试验一下。</span></span></span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(0,0,255); font-size: 13px; padding-top: 0px">&nbsp;</span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: arial; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;<span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(255,0,0); font-size: 13px; padding-top: 0px">&nbsp;Nagle算法是silly window syndrome(SWS)预防算法的一个半集。</span>SWS算法预防发送少量的数据，<span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">Nagle算法是其在发送方的实现，而接收方要做的时不要通告缓冲空间的很小增长，不通知小窗口，除非</span>缓冲区空间有显著的增长。这里显著的增长定义为完全大小的段（MSS）或增长到大于最大窗口的一半。</span><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(0,0,255); font-size: 13px; padding-top: 0px">注意</span>：</span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">BSD的实现是允许在空闲链接上发送大的写操作剩下的最后的小段，也就是说，当超过1个MSS数据发送时，内核先依次发送完n个MSS的数据包，然后再发送尾部的小数据包，其间不再延时等待。（假设网络不阻塞且接收窗口足够大）</span></span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: 黑体; color: rgb(17,17,17); font-size: 14px; padding-top: 0px"><strong style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">TCP_NODELAY 选项</span></strong></span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: arial; color: rgb(51,51,51); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;默认情况下，发送数据采用Negale 算法。这样虽然提高了网络吞吐量，但是实时性却降低了，在一些交互性很强的应用程序来说是不允许的，使用TCP_NODELAY选项可以禁</span>止Negale 算法。</span>&nbsp;</p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: arial; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;此时，应用程序向内核递交的每个数据包都会立即发送出去。</span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(0,0,255); font-size: 13px; padding-top: 0px">需要注意的是，虽然禁止了Negale 算法，但网络的传输仍然受到TCP确认延迟机制的影响。</span><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><strong style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">TCP_CORK 选项</span></strong></span></span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">&nbsp;</span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: arial; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;所谓的</span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">CORK</span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">就是塞子的意思，形象地理解就是用</span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">CORK</span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">将连接塞住，使得数据先不发出去，等到拔去塞子后再发出去。设置该选项后，内核会尽力把小数据包拼接成一个大的数据包（一个MTU）再发送出去，当然若一定时间后（一般为200ms，该值尚待确认），内核仍然没有组合成一个MTU时也必须发送现有的数据（不可能让数据一直等待吧）。</span><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;然而，TCP_CORK的实现可能并不像你想象的那么完美，CORK并不会将连接完全塞住。内核其实并不知道应用层到底什么时候会发送第二批数据用于和第一批数据拼接以达到MTU的大小，因此内核会给出一个时间限制，在该时间内没有拼接成一个大包（努力接近MTU）的话，内核就会无条件发送。</span></span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(0,0,255); font-size: 13px; padding-top: 0px">也就是说若应用层程序发送小包数据的间隔不够短时，<span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">TCP_CORK就没有一点作用，反而失去了数据的实时性（每个小包数据都会延时一定时间再发送）。</span></span><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><strong style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">Nagle算法与</strong></span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: medium; padding-top: 0px"><strong style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">CORK算法区别</span><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /></strong></span><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /></span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">　　Nagle算法和CORK算法非常类似，但是它们的着眼点不一样，</span><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(0,0,255); font-size: 13px; padding-top: 0px">Nagle算法主要避免网络因为太多的小包（协议头的比例非常之大）而拥塞，而CORK算法则是为了提高网络的利用率，使得总体上协议头占用的比例尽可能的小</span>。<span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">如此看来这二者在避免发送小包上是一致的，在用户控制的层面上，Nagle算法完全不受用户socket的控制，你只能简单的设置TCP_NODELAY而禁用它，CORK算法同样也是通过设置或者清除TCP_<span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px">CORK</span>使能或者禁用之，然而Nagle算法关心的是网络拥塞问题，只要所有的ACK回来则发包，而CORK算法却可以关心内容，在前后数据包发送间隔很短的前提下（很重要，否则内核会帮你将分散的包发出），即使你是分散发送多个小数据包，你也可以通过使能CORK算法将这些内容拼接在一个包内，如果此时用Nagle算法的话，则可能做不到这一点。</span></span></span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: arial; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">&nbsp;</span></span></span></p>
<p style="padding-bottom: 0px; text-indent: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: arial; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(17,17,17); font-size: 13px; padding-top: 0px"><span style="padding-bottom: 0px; line-height: 1.8em; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(51,51,51); font-size: 13px; padding-top: 0px">参考：<a style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; color: rgb(0,102,204); text-decoration: underline; padding-top: 0px" href="http://www.cnblogs.com/ggjucheng/archive/2012/02/03/2337046.html">http://www.cnblogs.com/ggjucheng/archive/2012/02/03/2337046.html</a></span></span></span></p></div></div><img src ="http://www.cppblog.com/tx7do/aggbug/191900.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-09-25 03:08 <a href="http://www.cppblog.com/tx7do/archive/2012/09/25/191900.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于使用libcurl的注意事项</title><link>http://www.cppblog.com/tx7do/archive/2012/02/20/166048.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Mon, 20 Feb 2012 03:39:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/02/20/166048.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/166048.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/02/20/166048.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/166048.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/166048.html</trackback:ping><description><![CDATA[<strong style="font-size: 18pt">libcurl与CLOSE_WAIT</strong><br /><span style="color: red">转载自：</span><a href="http://blog.sunshow.net/2010/03/libcurl-and-close-wait/"><span style="color: red">http://blog.sunshow.net/2010/03/libcurl-and-close-wait/</span></a><br /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 15px/21px Georgia, Times, 'Times New Roman', serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span">
<p style="border-bottom-style: none; padding-bottom: 0px; background-color: transparent; margin: 0px 0px 21px; outline-style: none; outline-color: ; border-left-style: none; padding-left: 0px; padding-right: 0px; border-top-style: none; border-right-style: none; font-size: 15px; vertical-align: baseline; text-decoration: none; padding-top: 0px; background-origin: initial; background-clip: initial">调用libcurl下载，然后使用netstat查看发现有大量的TCP连接保持在CLOSE_WAIT状态<br />查看libcurl的文档说明，有这样一个选项：</p>
<blockquote style="border-bottom-style: none; padding-bottom: 0px; background-color: transparent; font-style: italic; margin: 0px 2.5em; outline-style: none; outline-color: ; border-left-style: none; padding-left: 0px; padding-right: 0px; border-top-style: none; color: rgb(85,85,85); border-right-style: none; font-size: 15px; vertical-align: baseline; quotes: none; text-decoration: none; padding-top: 0px; background-origin: initial; background-clip: initial">
<p style="border-bottom-style: none; padding-bottom: 0px; background-color: transparent; margin: 0px 0px 21px; outline-style: none; outline-color: ; border-left-style: none; padding-left: 0px; padding-right: 0px; border-top-style: none; border-right-style: none; font-size: 15px; vertical-align: baseline; text-decoration: none; padding-top: 0px; background-origin: initial; background-clip: initial">CURLOPT_FORBID_REUSE</p>
<p style="border-bottom-style: none; padding-bottom: 0px; background-color: transparent; margin: 0px 0px 21px; outline-style: none; outline-color: ; border-left-style: none; padding-left: 0px; padding-right: 0px; border-top-style: none; border-right-style: none; font-size: 15px; vertical-align: baseline; text-decoration: none; padding-top: 0px; background-origin: initial; background-clip: initial">Pass a long. Set to 1 to make the next transfer explicitly close the connection when done. Normally, libcurl keeps all connections alive when done with one transfer in case a succeeding one follows that can re-use them. This option should be used with caution and only if you understand what it does. Set to 0 to have libcurl keep the connection open for possible later re-use (default behavior).</p></blockquote>
<p style="border-bottom-style: none; padding-bottom: 0px; background-color: transparent; margin: 0px 0px 21px; outline-style: none; outline-color: ; border-left-style: none; padding-left: 0px; padding-right: 0px; border-top-style: none; border-right-style: none; font-size: 15px; vertical-align: baseline; text-decoration: none; padding-top: 0px; background-origin: initial; background-clip: initial">也就是说，默认情况下libcurl完成一个任务以后，出于重用连接的考虑不会马上关闭<br />如果没有新的TCP请求来重用这个连接，那么只能等到CLOSE_WAIT超时，这个时间默认在7200秒甚至更高，太多的CLOSE_WAIT连接会导致性能问题</p>
<p style="border-bottom-style: none; padding-bottom: 0px; background-color: transparent; margin: 0px 0px 21px; outline-style: none; outline-color: ; border-left-style: none; padding-left: 0px; padding-right: 0px; border-top-style: none; border-right-style: none; font-size: 15px; vertical-align: baseline; text-decoration: none; padding-top: 0px; background-origin: initial; background-clip: initial">解决方法：</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif" /><span style="color: #000000">curl_easy_setopt(curl,&nbsp;CURLOPT_FORBID_REUSE,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);</span></div>
<p style="border-bottom-style: none; padding-bottom: 0px; background-color: transparent; margin: 0px 0px 21px; outline-style: none; outline-color: ; border-left-style: none; padding-left: 0px; padding-right: 0px; border-top-style: none; border-right-style: none; font-size: 15px; vertical-align: baseline; text-decoration: none; padding-top: 0px; background-origin: initial; background-clip: initial"><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 15px/21px Georgia, Times, 'Times New Roman', serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span">&nbsp;最好再修改一下TCP参数调低CLOSE_WAIT和TIME_WAIT的超时时间</p>
<div style="border-bottom-style: none; padding-bottom: 0px; background-color: transparent; margin: 0px; outline-style: none; outline-color: ; border-left-style: none; padding-left: 0px; padding-right: 0px; border-top-style: none; border-right-style: none; clear: both; font-size: 15px; vertical-align: baseline; text-decoration: none; padding-top: 0px; background-origin: initial; background-clip: initial"></div>
<p style="border-bottom-style: none; padding-bottom: 0px; background-color: transparent; margin: 0px 0px 21px; outline-style: none; outline-color: ; border-left-style: none; padding-left: 0px; padding-right: 0px; border-top-style: none; border-right-style: none; font-size: 15px; vertical-align: baseline; text-decoration: none; padding-top: 0px; background-origin: initial; background-clip: initial"></span><br /><br /><br /><strong style="font-size: 18pt">libcurl 使用笔记</strong><br /><span style="color: red">转载自：</span><a href="http://gcoder.blogbus.com/logs/54871550.html"><span style="color: red">http://gcoder.blogbus.com/logs/54871550.html</span></a><br /></p>
<p>libcurl 是一个很不错的库，支持http，ftp等很多的协议。使用库最大的心得就是，不仔细看文档，仅仅看着例子就写程序，是一件危险的事情。我的程序崩溃了，我怀疑是自己代码写的问题，后来发现是库没用对。不仔细看文档（有时候文档本身也比较差劲，这时除了看仔细外，还要多动脑子，考虑它是怎么实现的），后果很严重。不加思索的使用别人的库或者代码，有时候很惬意，但是出问题时，却是寝食难安的。</p>
<p>1. CURLcode curl_global_init(long flags); 在多线程应用中，需要在主线程中调用这个函数。这个函数设置libcurl所需的环境。通常情况，如果不显式的调用它，第一次调用curl_easy_init()时，curl_easy_init 会调用 curl_global_init，在单线程环境下，这不是问题。但是多线程下就不行了，因为curl_global_init不是线程安全的。在多个线程中调用curl_easy_int，然后如果两个线程同时发现curl_global_init还没有被调用，同时调用curl_global_init，悲剧就发生了。这种情况发生的概率很小，但可能性是存在的。</p>
<p>2. libcurl 有个很好的特性，它甚至可以控制域名解析的超时。但是在默认情况下，它是使用alarm + siglongjmp 实现的。用alarm在多线程下做超时，本身就几乎不可能。如果只是使用alarm，并不会导致程序崩溃，但是，再加上siglongjmp，就要命了（程序崩溃的很可怕，core中几乎看不出有用信息），因为其需要一个sigjmp_buf型的全局变量，多线程修改它。（通常情况下，可以每个线程一个 sigjmp_buf 型的变量，这种情况下，多线程中使用 siglongjmp 是没有问题的，但是libcurl只有一个全局变量，所有的线程都会用）。</p>
<p>&nbsp; 具体是类似 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L) 的超时设置，导致alarm的使用（估计发生在域名解析阶段），如前所述，这在多线程中是不行的。解决方式是禁用掉alarm这种超时， curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L)。</p>
<p>&nbsp; 这样，多线程中使用超时就安全了。但是域名解析就没了超时机制，碰到很慢的域名解析，也很麻烦。文档的建议是 Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which enables nice timeouts for name resolves without signals.&nbsp; c-ares 是异步的 DNS 解决方案。</p>
<p><br /><br class="Apple-interchange-newline" /></span><br />&nbsp;<span style="font-size: 18pt"><strong>libcurl 多线程使用注意事项</strong></span><br /><span style="color: red">转载自:</span><a href="http://blog.csdn.net/jaylong35/article/details/6439549"><span style="color: red">http://blog.csdn.net/jaylong35/article/details/6439549</span></a><br /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Arial; white-space: normal; orphans: 2; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span"> </p>
<p>1、问题来源，多线程使用Libcurl导致程序跑一段时间后自己退出，没有明显的异常。找不到合适的BUG。</p>
<p>&nbsp;最后通过查看资料和网上找的一些文章，发现，原来是信号处理的问题：</p>
<p><span class="nroffip"><strong>CURLOPT_NOSIGNAL</strong></span></p>
<p class="level0"><span class="nroffip"><strong></strong></span></p>
<p class="level1">Pass a long. If it is 1, libcurl will not use any functions that install signal handlers or any functions that cause signals to be sent to the process.<span class="Apple-converted-space">&nbsp;</span><span style="font-family: mceinline">This option is mainly here to allow multi-threaded unix applications to still set/use all timeout options etc, without risking getting signals.<span class="Apple-converted-space">&nbsp;</span></span>(Added in 7.10)</p>
<p class="level1">If this option is set and libcurl has been built with the standard name resolver, timeouts will not occur while the name resolve takes place. Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which enables nice timeouts for name resolves without signals.</p>
<p class="level1">Setting<span class="Apple-converted-space">&nbsp;</span><a style="color: rgb(51,102,153); text-decoration: none" class="emphasis" href="http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTNOSIGNAL">CURLOPT_NOSIGNAL</a><span class="Apple-converted-space">&nbsp;</span>to 1 makes libcurl NOT ask the system to ignore SIGPIPE signals, which otherwise are sent by the system when trying to send data to a socket which is closed in the other end. libcurl makes an effort to never cause such SIGPIPEs to trigger, but some operating systems have no way to avoid them and even on those that have there are some corner cases when they may still happen, contrary to our desire.&nbsp;</p>
<p class="level1">就是当多个线程都使用超时处理的时候，同时主线程中有sleep或是wait等操作。如果不设置这个选项，libcurl将会发信号打断这个wait从而导致程序退出。</p>
<p class="level1">所以，在使用的时候把这个选项设置成1就可以了.</p>
<p class="level1">curl_setopt(curl,&nbsp;CURLOPT_NOSIGNAL, 1L);</p>
<p class="level1"><br />2、关于libcurl库的初始化和关闭：curl_global_init()和curl_global_cleanup()</p>
<p class="level1">这两个函数并不是线程安全的。所以只能在主线程中进行一次的初始化和清除。</p>
<p class="level1">虽然这个不是一定就会有问题，但是如果不这样处理还是有概率发生的。</span></p><img src ="http://www.cppblog.com/tx7do/aggbug/166048.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-02-20 11:39 <a href="http://www.cppblog.com/tx7do/archive/2012/02/20/166048.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>wininet 和“锟斤拷”</title><link>http://www.cppblog.com/tx7do/archive/2012/02/19/166014.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Sun, 19 Feb 2012 15:07:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/archive/2012/02/19/166014.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/166014.html</wfw:comment><comments>http://www.cppblog.com/tx7do/archive/2012/02/19/166014.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/166014.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/166014.html</trackback:ping><description><![CDATA[转载自：<a href="http://www.superfection.com/blog/?p=43">http://www.superfection.com/blog/?p=43</a><br /><br />
<p>魔爪的作者Djunny曾经说过，下载的主要问题是要熟悉各个网络的不同特点（比中文确切的英文单词应该是whimsicalness）。这点我现在是深有体会。比如大部分网站的url是基于utf8的，但是有些却是基于GB2312的，这些网站wininet可能不能正确处理。</p>
<p>其实ie是能正确处理的，但是微软却没有把相应的功能放到wininet里面，这目的只有一个，微软想使得ie的功能比wininet多一点，也就是故意要让程序员麻烦一些。何苦？你让人家难受，人家自然要找你的漏洞。</p>
<p>为何不放弃wininet而用liburl之类的程序，毕竟后者若干年的开发，久经考验。原因：做个简单的工具虽然可以用libcurl，但是发布uread这样的应用就不好，要至少多一个dll，麻烦。</p>
<p>好，下面谈谈&#8220;锟斤拷&#8221;的问题。其实这个问题已经有人谈过，参见 <a href="http://hooopo.javaeye.com/blog/352451">http://hooopo.javaeye.com/blog/352451</a>. 但是这里是由wininet引起的。采用简单的wininet调用，访问：</p>
<p><a href="http://www.sjtxt.com/soft/download.asp?softid=21519&amp;downid=2&amp;id=21525">http://www.sjtxt.com/soft/download.asp?softid=21519&amp;downid=2&amp;id=21525</a></p>
<p>你会发现重定向到一个网址：</p>
<p><a href="http://down1.sjtxt.com/2010-2/">http://down1.sjtxt.com/2010-2/</a>锟斤拷士锟斤拷陆.rar</p>
<p>为什么这里显示&#8220;锟斤拷&#8221;，就是wininet没有正确地解码，把这个网站返回的gb码当成utf8, 先转为utf16,然后又转成utf8,最后按照gb显示出来就变成了&#8220;锟斤拷&#8221;了（实际的转向地址为<a href="http://down1.sjtxt.com/2010-2/">http://down1.sjtxt.com/2010-2/</a>斗士大陆.rar，感兴趣的可以把这个&#8220;锟斤拷&#8221;如何出来的详细推演一下）。</p>
<p>处理这个问题的办法是不要让wininet进行自动重定向（301 302之类），自己进行处理。这下更麻烦了，本来用wininet就是为了省事，没想到却要多写若干代码。</p>
<p>还有一个可笑的事情是，wininet的ansi版本和unicode版本不同，后者自动地把url的path部分当成utf8处理，而前者不会。我有些工具是用delphi7写的，有些是用delphi 2010写的，对某些网站，后者则要调用以下这样的函数</p>
<p>InternetSetOption(hSession, 100{INTERNET_OPTION_CODEPAGE_PATH}, @CP_CHINA, sizeof(CP_CHINA));</p>
<p>其中最新的常量，Delphi中还没有定义（CP_CHINA = 936）。</p>
<p>这些问题的解决，只是把工具做的好一些。实际上没有什么意义，都是微软没有把事情做好。你做好点，大家就可以做些有意义的事情是不？</p>
<p>&nbsp;</p><img src ="http://www.cppblog.com/tx7do/aggbug/166014.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2012-02-19 23:07 <a href="http://www.cppblog.com/tx7do/archive/2012/02/19/166014.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>