AudioFlinger分析(7)

2020-02-20 14:13

size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;

numFrames -= outFrames; frameCount0 -= outFrames; frameCount1 -= outFrames; do {

int32_t l0 = *in0++; int32_t r0 = *in0++; l0 = mul(l0, vl0); r0 = mul(r0, vr0); int32_t l = *in1++; int32_t r = *in1++;

l = mulAdd(l, vl1, l0) >> 12; r = mulAdd(r, vr1, r0) >> 12; // clamping... l = clamp16(l); r = clamp16(r);

*out++ = (r<<16) | (l & 0xFFFF); } while (--outFrames);

if (frameCount0 == 0) {

t0.bufferProvider->releaseBuffer(&b0); }

if (frameCount1 == 0) {

t1.bufferProvider->releaseBuffer(&b1); } }

if (buff != NULL) { delete [] buff; }

}

看不懂了吧??哈哈,知道有这回事就行了,专门搞数字音频的需要好好研究下了!

三再论共享audio_track_cblk_t

为什么要再论这个?因为我在网上找了下,有人说audio_track_cblk_t是一个环形buffer,环形buffer是什么意思?自己查查!

这个吗,和我之前的工作经历有关系,某BOSS费尽心机想搞一个牛掰掰的环形buffer,搞得我累死了。现在audio_track_cblk_t是环形buffer?我倒是想看看它是怎么实现的。 顺便我们要解释下,audio_track_cblk_t的使用和我之前说的Lock,读/写,Unlock不太一样。为何?

? 第一因为我们没在AF代码中看到有缓冲buffer方面的wait,MixThread只有当没有数据的时候会usleep一下。

? 第二,如果有多个track,多个audio_track_cblk_t的话,假如又是采用wait信号的办法,那么由于pthread库缺乏WaitForMultiObjects的机制,那么到底该等哪一个?这个问题是我们之前在做跨平台同步库的一个重要难题。

1. 写者的使用

我们集中到audio_track_cblk_t这个类,来看看写者是如何使用的。写者就是AudioTrack端,在这个类中,叫user

? framesAvailable,看看是否有空余空间 ? buffer,获得写空间起始地址 ? stepUser,更新user的位置。

2. 读者的使用

读者是AF端,在这个类中加server。

? framesReady,获得可读的位置 ? stepServer,更新读者的位置

看看这个类的定义:

struct audio_track_cblk_t {

Mutex lock; //同步锁 Condition cv;//CV volatile uint32_t user;//写者 volatile uint32_t server;//读者

uint32_t userBase;//写者起始位置 uint32_t serverBase;//读者起始位置 void* buffers; uint32_t frameCount; // Cache line boundary

uint32_t loopStart; //循环起始

uint32_t loopEnd; //循环结束 int loopCount;

uint8_t out; //如果是Track的话,out就是1,表示输出。 }

注意这是volatile,跨进程的对象,看来这个volatile也是可以跨进程的嘛。

? 唉,又要发挥下了。volatile只是告诉编译器,这个单元的地址不要cache到CPU的缓冲中。也就是每次取值的时候都要到实际内存中去读,而且可能读内存的时候先要锁一下总线。防止其他CPU核执行的时候同时去修改。由于是跨进程共享的内存,这块内存在两个进程都是能见到的,又锁总线了,又是同一块内存,volatile当然保证了同步一致性。

? loopStart和loopEnd这两个值是表示循环播放的起点和终点的,下面还有一个loopCount吗,表示循环播放次数的

那就分析下吧。 先看写者的那几个函数 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;


AudioFlinger分析(7).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:华理工 宏观经济学 - 201606 - 模拟卷2

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: