关于安卓AudioTrack::getMinFrameCount的分析

本文详细解析了音频缓冲区计算的原理与方法,包括如何确保软件侧缓冲区大小能满足硬件延迟需求,以及不同采样率下缓冲区帧数的计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载自http://www.cnblogs.com/andriod-html5/archive/2012/06/06/2539531.html,感谢大神分享


  1. // Ensure that buffer depth covers at least audio hardware latency  
  2. uint32_t minBufCount = afLatency / ((1000 * afFrameCount) / afSampleRate);  

minBufCount = 200 / ((1000×1536)/44100) = 5.


消化消化。
afFrameCount的意思是硬件buffer里能放多少frame,afFrameCount/afSampleRate的意思是,播放一次硬件buffer中的数据需要多少时间,算出来的单位是秒。
再乘以个1000,即将秒转为了毫秒。
这样就与afLatency的单位一致了。
这样算出来的结果,就是说,为了满足硬件延迟,软件侧的buffer大小只是要是硬件侧buffer大小的多少倍。


感觉还是没消化彻底。
什么是硬件延迟?为什么软件侧的buffer size需要这个倍数呢?
硬件延迟,就是说,硬件侧可能会延迟这么久,也就是说硬件可能有这么长的时间都没有从软件侧取数据。
而软件侧还在不停地写数据,为了保证软件侧的数据不被丢失,就需要软件侧的buffer足够大。
多大才是足够大呢?
就是在硬件允许的最大时间,不取数据的情况下,软件侧的buffer也不至于爆仓。
这样基本上消化彻底了。


frameCount的计算与传入参数sampleRate有关:

  1. *frameCount = (sampleRate == 0) ? afFrameCount * minBufCount :  
  2.           afFrameCount * minBufCount * sampleRate / afSampleRate;  

如果sampleRate为0,frameCount为7680.
如果sampleRate不为0,frameCount为7680×sampleRate/44100.


消化一下。
既然上面已经算出来了软件buffer 大小只是要是硬件的多少倍,而硬件buffer中包含的frame个数已经知道为afFrameCount,
算出软件buffer中包含多少frame也没什么困难了。
如果软件侧过来的数据与硬件侧的sampling rate未指定,或者与硬件侧的一样,软件侧的buffer能装的frame个数即为afFrameCount * minBufCount。

如果软件侧的sampling rate与硬件侧不一致,就拿上面的结果再乘以个sampleRate / afSampleRate即可。


         基于以上大神分析,加上我的理解总结如下:

uint32_t minBufCount = afLatency / ((1000 * afFrameCount) / afSampleRate);

afFrameCount为硬件buffer一次能够播放多少个frame,单位为frame。

afSampleRate为每秒采样多少个frame。

afFrameCount/afSampleRate表示硬件buffer能够一次播放多少秒的数据。乘以1000表示播放多少ms的数据。

afLatency 硬件延迟表示硬件从第一次取数据到第二次去数据总共花了多少ms。

所以minBufCount表示上层需要最少准备多少个硬件buffer大小的软件buffer,才能保证传输数据不会出现中断。单位为个。

afFrameCount * minBufCount * sampleRate / afSampleRate; 

afFrameCount * minBufCount表示我这个软件buffer里面有多少个frame。

sampleRate / afSampleRate可看成比值,即所需传输的采样率和硬件支持的采样率比值,表示我这个软件buffer如果用在传输实际sampleRate的数据的话,可以大一些,也可以小一些。那么就看这个比值了。以上公式就表示我软件buffer需要多少个frame才能保证不会断音。

frameCount * nbChannels * (audioFormat == ENCODING_PCM_16BIT ? 2 : 1);

再加上这个就表示我软件buffer需要多少个字节的空间了。

这个代码: static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) { int channelCount = 0; /*这里就是声道选择,单声道或则双声道*/ switch(channelConfig) { case AudioFormat.CHANNEL_OUT_MONO: case AudioFormat.CHANNEL_CONFIGURATION_MONO: channelCount = 1; break; case AudioFormat.CHANNEL_OUT_STEREO: case AudioFormat.CHANNEL_CONFIGURATION_STEREO: channelCount = 2; break; default: if (!isMultichannelConfigSupported(channelConfig)) { loge("getMinBufferSize(): Invalid channel configuration."); return ERROR_BAD_VALUE; } else { channelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig); } } if (!AudioFormat.isPublicEncoding(audioFormat)) { loge("getMinBufferSize(): Invalid audio format."); return ERROR_BAD_VALUE; } // sample rate, note these values are subject to change // Note: AudioFormat.SAMPLE_RATE_UNSPECIFIED is not allowed /*就是采样率,人耳朵在20hz到20khz之间。 *采样率支持:4KHz~192KHz好像可以找到设定的值 */ if ( (sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN) || (sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) ) { loge("getMinBufferSize(): " + sampleRateInHz + " Hz is not a supported sample rate."); return ERROR_BAD_VALUE; } /*frameworks/base/core/jni/android_media_AudioTrack.cpp中 android_media_AudioTrack_get_min_buff_size这个函数来实现的 */ int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat); if (size <= 0) { loge("getMinBufferSize(): error querying hardware"); return ERROR; } else { return size; } } 和这个代码:static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thiz, jint sampleRateInHertz, jint channelCount, jint audioFormat) { size_t frameCount; /*这个函数用于确定至少设置多少个 frame 才能保证声音正常播放,也就是最低帧数*/ const status_t status = AudioTrack::getMinFrameCount(&frameCount, AUDIO_STREAM_DEFAULT, sampleRateInHertz); if (status != NO_ERROR) { ALOGE("AudioTrack::getMinFrameCount() for sample rate %d failed with status %d", sampleRateInHertz, status); return -1; } const audio_format_t format = audioFormatToNative(audioFormat); if (audio_has_proportional_frames(format)) { const size_t bytesPerSample = audio_bytes_per_sample(format); /*PCM 数据最小缓冲区大小 *最小缓冲区的大小 = 最低帧数 * 声道数 * 采样深度,(采样深度以字节为单位) */ return frameCount * channelCount * bytesPerSample; } else { return frameCount; } } 是怎么联系起来的
最新发布
07-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值