2013年(10)
分类: 嵌入式
2013-04-03 08:20:43
原文地址:Android Audio CBLK的算法分析 作者:BENNYSNAKE
续接Android深入浅出之Audio 第二部分 AudioFlinger分析【转】
4 写者分析
先用frameavail看看当前剩余多少空间,我们可以假设是第一次进来嘛。读者还在那sleep呢。
uint32_t audio_track_cblk_t::framesAvailable()
{
Mutex::Autolock _l(lock);
return framesAvailable_l();
}
int32_t audio_track_cblk_t::framesAvailable_l()
{
uint32_t u = this->user; 当前写者位置,此时也为0
uint32_t s = this->server; //当前读者位置,此时为0
if (out) { out为1
uint32_t limit = (s < loopStart) ? s : loopStart;
我们不设循环播放时间吗。所以loopStart是初始值INT_MAX,所以limit=0
return limit + frameCount - u;
//返回0+frameCount-0,也就是全缓冲最大的空间。假设frameCount=1024帧
}
}
然后调用buffer获得其实位置,buffer就是得到一个地址位置。
void* audio_track_cblk_t::buffer(uint32_t offset) const
{
return (int8_t *)this->buffers + (offset - userBase) * this->frameSize;
}
完了,我们更新写者,调用stepUser
uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount)
{
//framecount,表示我写了多少,假设这一次写了512帧
uint32_t u = this->user;//user位置还没更新呢,此时u=0;
u += frameCount;//u更新了,u=512
// Ensure that user is never ahead of server for AudioRecord
if (out) {
//没甚,计算下等待时间
}
//userBase还是初始值为0,可惜啊,我们只写了1024的一半
//所以userBase加不了
if (u >= userBase + this->frameCount) {
userBase += this->frameCount;
//但是这句话很重要,userBase也更新了。根据buffer函数的实现来看,似乎把这个
//环形缓冲铺直了....连绵不绝。
}
this->user = u;//喔,user位置也更新为512了,但是useBase还是0
return u;
}
好了,假设写者这个时候sleep了,而读者起来了。
5 读者分析
uint32_t audio_track_cblk_t::framesReady()
{
uint32_t u = this->user; //u为512
uint32_t s = this->server;//还没读呢,s为零
if (out) {
if (u < loopEnd) {
return u - s;//loopEnd也是INT_MAX,所以这里返回512,表示有512帧可读了
} else {
Mutex::Autolock _l(lock);
if (loopCount >= 0) {
return (loopEnd - loopStart)*loopCount + u - s;
} else {
return UINT_MAX;
}
}
} else {
return s - u;
}
}
使用完了,然后stepServer
bool audio_track_cblk_t::stepServer(uint32_t frameCount)
{
status_t err;
err = lock.tryLock();
uint32_t s = this->server;
s += frameCount; //读了512帧了,所以s=512
if (out) {
}
没有设置循环播放嘛,所以不走这个
if (s >= loopEnd) {
s = loopStart;
if (--loopCount == 0) {
loopEnd = UINT_MAX;
loopStart = UINT_MAX;
}
}
//一样啊,把环形缓冲铺直了
if (s >= serverBase + this->frameCount) {
serverBase += this->frameCount;
}
this->server = s; //server为512了
cv.signal(); //读者读完了。触发下写者吧。
lock.unlock();
return true;
}
6 真的是环形缓冲吗?
环形缓冲是这样一个场景,现在buffer共1024帧。
假设:
l 写者先写到1024帧
l 读者读到512帧
l 那么,写者还可以从头写512帧。
所以,我们得回头看看frameavail是不是把这512帧算进来了。
uint32_t audio_track_cblk_t::framesAvailable_l()
{
uint32_t u = this->user; //1024
uint32_t s = this->server;//512
if (out) {
uint32_t limit = (s < loopStart) ? s : loopStart;
return limit + frameCount - u;返回512,用上了!
}
}
再看看stepUser这句话
if (u >= userBase + this->frameCount) {u为1024,userBase为0,frameCount为1024
userBase += this->frameCount;//好,userBase也为1024了
}
看看buffer
return (int8_t *)this->buffers + (offset - userBase) * this->frameSize;
//offset是外界传入的基于user的一个偏移量。offs