Android Alsa 参数和上层参数对应关系

来源:互联网 发布:人工智能代替老师 编辑:程序博客网 时间:2024/06/05 14:30

通过tinyalsa一般能看到硬件参数,比如NanoPC-T2的参数如下所示:

$ adb shell tinyalsa pcminfo -D 0Info for card 0, device 0:PCM out:      Access:   0x000009   Format[0]:   0x000004   Format[1]:   00000000 Format Name:   S16_LE   Subformat:   0x000001        Rate:   min=48000Hz max=48000Hz    Channels:   min=2       max=2 Sample bits:   min=16      max=16 Period size:   min=8       max=2048Period count:   min=2       max=64PCM in:      Access:   0x000009   Format[0]:   0x000004   Format[1]:   00000000 Format Name:   S16_LE   Subformat:   0x000001        Rate:   min=48000Hz max=48000Hz    Channels:   min=2       max=2 Sample bits:   min=16      max=16 Period size:   min=8       max=2048Period count:   min=2       max=64$

一般是有Rate Sample bits Period size Period count这几个参数,并且一部分参数是范围值。真正使用的需要看具体的平台的Audio HAL代码中的定义:

static struct snd_card_dev pcm_out = {    .name       = "PCM OUT",    .card       = 0,    .device     = 0,    .flags      = PCM_OUT,    .config     = {        .channels       = 2,        .rate           = 48000,        .period_size    = 1024,        .period_count   = 4,        .format         = PCM_FORMAT_S16_LE,    },};static struct snd_card_dev pcm_in = {    .name       = "PCM IN",    .card       = 0,    .device     = 0,    .flags      = PCM_IN,    .config     = {        .channels       = 2,        .rate           = 48000,        .period_size    = 1024,        .period_count   = 4,        .format         = PCM_FORMAT_S16_LE,    },};

但是程序里一般使用的是mFrameSize,mFrameCount,mBufferSize。它们之间的关系是什么呢?

mFrameSize = channels * format / 8 = 2 * 16 / 8 = 4;mBufferSize = period_size * mFrameSize = 1024 * 4 = 4096;mFrameCount = mBufferSize / mFrameSize = 4096 / 4 = 1024;

简单讲:就是period_size是可变了,它决定了上层的各个参数值。在HAL中将其设置小一点,上层的各种Size值就会小很多。比如period_size设置成最小的8。

mFrameSize = channels * format / 8 = 2 * 16 / 8 = 4;mBufferSize = period_size * mFrameSize = 8 * 4 = 32;mFrameCount = mBufferSize / mFrameSize = 32 / 4 = 8;

可以看到mFrameCount实质是等于period_size的值。AudioFlinger里目前要求的最合适的值是16。证据如下:
这里写图片描述

Over and Under Run

当一个声卡活动时,数据总是连续地在硬件缓存区和应用程序缓存区间传输。但是也有例外。在录音例子中,如果应用程序读取数据不够快,循环缓存区将会被新的数据覆盖。这种数据的丢失被称为overrun.在回放例子中,如果应用程序写入数据到缓存区中的速度不够快,缓存区将会”饿死”。这样的错误被称为”underrun”。在ALSA文档中,有时将这两种情形统称为”XRUN”。适当地设计应用程序可以最小化XRUN并且可以从中恢复过来。
来自:http://blog.csdn.net/zhang_danf/article/details/39005767

mNormalFrameCount和mFrameCount的关系

要使用FastMixer需要搞清楚mNormalFrameCountmFrameCount的关系,因为如果mFrameCount < mNormalFrameCount才会起用FastMixer

    // Calculate size of normal sink buffer relative to the HAL output buffer size    double multiplier = 1.0;    if (mType == MIXER && (kUseFastMixer == FastMixer_Static ||            kUseFastMixer == FastMixer_Dynamic)) {        size_t minNormalFrameCount = (kMinNormalSinkBufferSizeMs * mSampleRate) / 1000;        size_t maxNormalFrameCount = (kMaxNormalSinkBufferSizeMs * mSampleRate) / 1000;        // round up minimum and round down maximum to nearest 16 frames to satisfy AudioMixer        minNormalFrameCount = (minNormalFrameCount + 15) & ~15;        maxNormalFrameCount = maxNormalFrameCount & ~15;        if (maxNormalFrameCount < minNormalFrameCount) {            maxNormalFrameCount = minNormalFrameCount;        }        multiplier = (double) minNormalFrameCount / (double) mFrameCount;        if (multiplier <= 1.0) {            multiplier = 1.0;        } else if (multiplier <= 2.0) {            if (2 * mFrameCount <= maxNormalFrameCount) {                multiplier = 2.0;            } else {                multiplier = (double) maxNormalFrameCount / (double) mFrameCount;            }        } else {            // prefer an even multiplier, for compatibility with doubling of fast tracks due to HAL            // SRC (it would be unusual for the normal sink buffer size to not be a multiple of fast            // track, but we sometimes have to do this to satisfy the maximum frame count            // constraint)            // FIXME this rounding up should not be done if no HAL SRC            uint32_t truncMult = (uint32_t) multiplier;            if ((truncMult & 1)) {                if ((truncMult + 1) * mFrameCount <= maxNormalFrameCount) {                    ++truncMult;                }            }            multiplier = (double) truncMult;        }    }    mNormalFrameCount = multiplier * mFrameCount;        // round up to nearest 16 frames to satisfy AudioMixer    if (mType == MIXER || mType == DUPLICATING) {        mNormalFrameCount = (mNormalFrameCount + 15) & ~15;    }    ALOGI("HAL output buffer size %u frames, normal sink buffer size %u frames", mFrameCount,            mNormalFrameCount);
阅读全文
0 0
原创粉丝点击