今天来看看Android中的录音数据是怎么来的。
从AudioRecord开始看吧。
AudioRecord中可以取得录音数据的接口是:AudioRecord::read。
首先调用函数obtainBuffer取得录音数据的地址。
然后用memcpy将录音数据copy出来。
看样子,数据来源是obtainBuffer函数了。
来看看函数AudioRecord::obtainBuffer。
其主要功能就是对传入的audioBuffer进行赋值。
audioBuffer是Buffer* 类型。
看看Buffer类:
class Buffer
{
public:
enum {
MUTE = 0x00000001
};
uint32_t flags;
int channelCount;
int format;
size_t frameCount;
size_t size;
union {
void* raw;
short* i16;
int8_t* i8;
};
};
其中保存数据的是下面这块东东:
union {
void* raw;
short* i16;
int8_t* i8;
};
函数AudioRecord::obtainBuffer中对这块东东赋值的代码如下:
audioBuffer->raw = (int8_t*)cblk->buffer(u);
cblk的来历:
audio_track_cblk_t* cblk = mCblk;
mCblk的赋值在函数AudioRecord::openRecord中被赋值:
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); // 可见mCblk头部保存的是结构体的信息,后面跟的是数据
函数audio_track_cblk_t::buffer的实现:
void* audio_track_cblk_t::buffer(uint64_t offset) const
{
return (int8_t *)this->buffers + (offset - userBase) * this->frameSize;
}
可见数据就保存在audio_track_cblk_t结构体中。
是什么地方往结构体audio_track_cblk_t中写的数据呢?
发现函数AudioRecord::obtainBuffer中,在获取buffer地址时,首先会调用函数audio_track_cblk_t::framesReady来判断有多少数据准备好了。
想起来在播放数据的时候,使用audio_track_cblk_t中的数据时,也调用了函数audio_track_cblk_t::framesReady。
而往audio_track_cblk_t中写数据时,调用了函数audio_track_cblk_t::framesAvailable。
录音肯定也是这样的了。
也就是说,找到调用函数audio_track_cblk_t::framesAvailable的地方,也就找到了往audio_track_cblk_t中写数据的地方。
录音相关,调用audio_track_cblk_t::framesAvailable的地方如下:
AudioFlinger::RecordThread::RecordTrack::getNextBuffer函数。
函数AudioFlinger::RecordThread::RecordTrack::getNextBuffer的主要作用是给传入的AudioBufferProvider::Buffer赋值。
AudioBufferProvider::Buffer结构体类型:
struct Buffer {
union {
void* raw;
short* i16;
int8_t* i8;
};
size_t frameCount;
};
保存数据的是下面这块东东:
union {
void* raw;
short* i16;
int8_t* i8;
};
函数AudioFlinger::RecordThread::RecordTrack::getNextBuffer对这块东东赋值的代码如下:
buffer->raw = getBuffer(s, framesReq);
函数AudioFlinger::ThreadBase::TrackBase::getBuffer返回了一个int8_t型指针bufferStart。
对bufferStart赋值的代码如下:
int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
mBuffer的赋值在AudioFlinger::ThreadBase::TrackBase::TrackBase的构造函数中:
mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
mCblk 的来历:
mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer()); 或 new(mCblk) audio_track_cblk_t();
这个在研究播放音频流的时候已经看过,这儿就不重复了。
肯定是哪个地方调用了函数AudioFlinger::RecordThread::RecordTrack::getNextBuffer,获取一段buffer,然后将录音数据写入到这个buffer。
搜搜调用函数AudioFlinger::RecordThread::RecordTrack::getNextBuffer的地方,录音相关的调用有以下:
AudioFlinger::RecordThread::threadLoop函数
AudioFlinger::RecordThread::threadLoop函数中,调用函数AudioFlinger::RecordThread::RecordTrack::getNextBuffer获取了buffer。
然后将buffer赋值给了dst:
int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
下面要分两种情况来讨论了:
+++++++++++++++++++++++++++++++++++++++不需要resampling的情况-start++++++++++++++++++++++++++++++++++++++++++++++
往dst写数据的有以下两个地方:
while (framesIn--) {
*dst16++ = *src16;
*dst16++ = *src16++;
}
或:
while (framesIn--) {
*dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
src16 += 2;
}
也就是说数据来源是src了,看看src的由来。
int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
对mRsmpInBuffer赋值的地方在函数AudioFlinger::RecordThread::readInputParameters中:
mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
这儿只是new了个buffer,寻找数据来源,还要看哪儿往里面写数据了。
往 mRsmpInBuffer中写数据的地方也在AudioFlinger::RecordThread::threadLoop函数中:
mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
----------------------------------------不需要resampling的情况-end-----------------------------------------------
+++++++++++++++++++++++++++++++++++++++需要resampling的情况-start++++++++++++++++++++++++++++++++++++++++++++++
往dst写数据的地方:
while (framesOut--) {
*dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
src += 2;
}
也就是说数据来源是src了,看看src的由来。
int16_t *src = (int16_t *)mRsmpOutBuffer;
对mRsmpInBuffer赋值的地方在函数AudioFlinger::RecordThread::readInputParameters中:
mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
这儿只是new了个buffer,寻找数据来源,还要看哪儿往里面写数据了。
往 mRsmpInBuffer中写数据的地方在AudioFlinger::RecordThread::getNextBuffer函数中:
mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
下面看看对AudioFlinger::RecordThread::getNextBuffer函数的调用:
首先函数AudioFlinger::RecordThread::threadLoop中调用了函数AudioResamplerOrder1::resample。
mResampler->resample(mRsmpOutBuffer, framesOut, this);
函数AudioResamplerOrder1::resample调用了函数AudioResamplerOrder1::resampleMono16:
resampleMono16(out, outFrameCount, provider);
函数AudioResamplerOrder1::resampleMono16中调用了函数AudioFlinger::RecordThread::getNextBuffer:
provider->getNextBuffer(&mBuffer);
mResampler的赋值在函数AudioFlinger::RecordThread::readInputParameters中:
mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
函数AudioResampler::create根据参数,返回不同的resampler:
switch (quality) {
default:
case LOW_QUALITY:
LOGV("Create linear Resampler");
resampler = new AudioResamplerOrder1(bitDepth, inChannelCount, sampleRate);
break;
case MED_QUALITY:
LOGV("Create cubic Resampler");
resampler = new AudioResamplerCubic(bitDepth, inChannelCount, sampleRate);
break;
case HIGH_QUALITY:
LOGV("Create sinc Resampler");
resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate);
break;
}
从上面对函数AudioFlinger::RecordThread::getNextBuffer的调用可知,mRsmpOutBuffer最终作为参数out传给了函数AudioResamplerOrder1::resampleMono16。
最终往mRsmpOutBuffer中写数据的地方是在函数AudioResamplerOrder1::resampleMono16中:
// handle boundary case
while (inputIndex == 0) {
// LOGE("boundary case\n");
int32_t sample = Interp(mX0L, in[0], phaseFraction);
out[outputIndex++] += vl * sample;
out[outputIndex++] += vr * sample;
Advance(&inputIndex, &phaseFraction, phaseIncrement);
if (outputIndex == outputSampleCount)
break;
}
或:
while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) {
int32_t sample = Interp(in[inputIndex-1], in[inputIndex],
phaseFraction);
out[outputIndex++] += vl * sample;
out[outputIndex++] += vr * sample;
Advance(&inputIndex, &phaseFraction, phaseIncrement);
}
in的来历:
int16_t *in = mBuffer.i16;
mBuffer的赋值:
provider->getNextBuffer(&mBuffer);
回到了刚次说的对函数AudioFlinger::RecordThread::getNextBuffer的调用。
函数AudioFlinger::RecordThread::getNextBuffer中首先调用函数AudioStreamInALSA::read获取数据指针。
mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
然后将数据地址赋值给传入的AudioBufferProvider::Buffer指针:
buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
下面看看resampling对数据的处理。
int32_t sample = Interp(in[inputIndex-1], in[inputIndex],
phaseFraction);
phaseFraction的来源:
uint32_t phaseFraction = mPhaseFraction;
phaseFraction作为参数传给了函数Advance:
Advance(&inputIndex, &phaseFraction, phaseIncrement);
函数Advance中对phaseFraction进行了赋值:
static inline void Advance(size_t* index, uint32_t* frac, uint32_t inc) {
*frac += inc;
*index += (size_t)(*frac >> kNumPhaseBits);
*frac &= kPhaseMask;
}
常量的定义:
// number of bits for phase fraction - 28 bits allows nearly 8x downsampling
static const int kNumPhaseBits = 28;
// phase mask for fraction
static const uint32_t kPhaseMask = (1LU<<kNumPhaseBits)-1;
再看看Interp函数:
static inline int32_t Interp(int32_t x0, int32_t x1, uint32_t f) {
return x0 + (((x1 - x0) * (int32_t)(f >> kPreInterpShift)) >> kNumInterpBits);
}
常量定义:
// number of bits used in interpolation multiply - 15 bits avoids overflow
static const int kNumInterpBits = 15;
// bits to shift the phase fraction down to avoid overflow
static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits;
再看vl和vr:
int32_t vl = mVolume[0];
int32_t vr = mVolume[1];
mVolume在函数AudioResampler::setVolume中被赋值:
void AudioResampler::setVolume(int16_t left, int16_t right) {
// TODO: Implement anti-zipper filter
mVolume[0] = left;
mVolume[1] = right;
}
函数AudioResampler::setVolume在函数AudioFlinger::RecordThread::readInputParameters中被调用:
mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
常量定义:
static const uint16_t UNITY_GAIN = 0x1000;
----------------------------------------需要resampling的情况-end-----------------------------------------------
可以,无论是否resampling,都是通过调用函数AudioStreamInALSA::read来获取数据。
函数AudioStreamInALSA::read中调用了ALSA Lib中的函数snd_pcm_mmap_readi或函数snd_pcm_readi来取得数据:
if (mHandle->mmap)
n = snd_pcm_mmap_readi(mHandle->handle, buffer, frames);
else
n = snd_pcm_readi(mHandle->handle, buffer, frames);