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

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

$ adb shell tinyalsa pcminfo -D 0
Info 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=2048
Period count:   min=2       max=64

PCM 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=2048
Period 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
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

袁保康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值