Android Audio 01 - Control Block

来源:互联网 发布:网络兼职赚钱平台 编辑:程序博客网 时间:2024/06/07 00:30

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.

原创粉丝点击