Android Audio 01 - Control Block

Audio CB: audio_track_cblk_t


userBase, serverBase, frameCount, stepUser, stepServer, buffer, frameAvailable, frameReady

userBase: 写数据的基数位置

serverBase: 读数据的基数位置

FrameCount: 读写大小

stepUser:更新写数据的位置

stepServer: 更新读数据的位置

underrun模式:生产者跟不上消费者,消费者得wait,生产者有数据了signal

生产者:obtainBuffer/memcpy/releaseBuffer

消费者: getNextBuffer/releaseBuffer

-------------------------------------------------------------------------------------------

cblk_t      |                  server读 |               user写                |                |

-------------------------------------------------------------------------------------------

stepUSER() and stepServer的作用是调整当前偏移的位置,可以看到,他们仅仅是把成员变量user server的值加上需要移动的数量,user和server的值并不考虑FIFO的边界问题,随着数据的不停写入和读出,user和server的值不断增加,只要处理得当,user总是出现在server的后面,因此frameAvailable和frameReady才会成立。根据这种算法,user和server都会大于FIFO的大小,frameCount,那么如何确定真正的写指针的位置了?需要用到userbase这个变量。在stepUser中,每当user的值越过(UserBase+farmeCount) userBase就会增加frameCount,这样映射到FIFO中的偏移总是可以通过user-userBase获得。因此,获得当前FIFO的写指针可以通过buffer()返回

p = mCblk->buffer(mcblk->user)

---------------- 华华丽丽的分割线----------------------------------

细读了android中关于audio这块的源码,发现有个地方设计的挺巧妙的。

他将一块有限的线性buffer,变成了可以循环的环形缓冲,生产者/消费者模式

原来的代码函数是,frameAvaliable Buffer stepUser// frameReady/stepServer etc.

我稍微简化了些,留作以后可能需要生产者/消费者的读写I/O

  1 const int bufferSize = 1000;
  2 const int loopStart = 1000;
  3 //userBase = everytime the buffer write cross the scope,
  4 //loop to the first place, userBase += bufferSize
  5
  6 /*
  7  * buffer():provide the init position for write
  8  */
  9 void* audio_track_cblk_t::buffer(int write) const
 10 {
 11         return buffers + write - userBase;
 12 }
 13 //how many bytes could be available
 14 int audio_track_cblk_t::bufferAvailable()
 15 {
 16     int limit = (read < loopStart) ? read : loopStart;
 17     return limit + loopStart - write;
 18 }
 19 int audio_track_cblk_t::updateWrite(int frameCount)//frameCount is how many bytes been written
 20 {
 21     //update the position of write
 22     write += frameCount;
 23     if (write >= userBase + bufferSize){
 24         userBase += bufferSize;//userBase will loop to the front
 25     }
 26     return write;
 27 }
 28 int audio_track_cblk_t::bufferCouldRead()
 29 {
 30 // write will always larger than read position
 31 // whenever the loop has happened
 32 // the max gap between write and read will be bufferSize
 33             return write - read;
 34 }
 35 bool audio_track_cblk_t::updateReadPos(int frameCount)
 36 {
 37     LOG("after read, update the read position");
 38     LOG("frameCount is the buffer size been read");
 39     read+= frameCount;
 40
 41     if ( read >= userBase + bufferSize)
 42         userBase += bufferSize;
 43
 44     signal();//signal the write side
 45     return true;
 46 }

 

稍微说明:

bufferSize就是这块线性内存的大小,userBase其实一直被增长,但是每次都是bufferSize的整数倍,当write越界了,超过bufferSize了,比如写了1300,bufferSize才1000,那userBase就必须加上1000,这样write-userBase=300,这样才是正确的相对写位置。读位置同理。

write要一直比read快,否则生产者/消费者模型就有问题了。wait/signal/broadcast/ could help.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值