【Android多媒体(重采样与混频)】重采样等基本概念
来源:互联网 发布:什么叫开车 网络用词 编辑:程序博客网 时间:2024/06/03 23:57
重采样和混频的概念
关于音频采样,百度上面找到这样的解答:
频率对应于时间轴线,振幅对应于电平轴线。波是无限光滑的,弦线可以看成由无数点组成,由于存储空间是相对有限的,数字编码过程中,必须对弦线的点进行采样。采样的过程就是抽取某点的频率值,很显然,在一秒中内抽取的点越多,获取得频率信息更丰富,为了复原波形,一次振动中,必须有2个点的采样,人耳能够感觉到的最高频率为20kHz,因此要满足人耳的听觉要求,则需要至少每秒进行40k次采样,用40kHz表达,这个40kHz就是采样率。我们常见的CD,采样率为44.1kHz。光有频率信息是不够的,我们还必须获得该频率的能量值并量化,用于表示信号强度。量化电平数为2的整数次幂,我们常见的CD位16bit的采样大小,即2的16次方。采样大小相对采样率更难理解,因为要显得抽象点,举个简单例子:假设对一个波进行8次采样,采样点分别对应的能量值分别为A1-A8,但我们只使用2bit的采样大小,结果我们只能保留A1-A8中4个点的值而舍弃另外4个。如果我们进行3bit的采样大小,则刚好记录下8个点的所有信息。采样率和采样大小的值越大,记录的波形更接近原始信号
而重采样,就是为了满足播放与存储的需求,使用某种插值或者抽取的算法,改变采样率的过程。
Android系统中间的重采样与混频
再android多媒体系统中间:
录音线程RecordThread直接调用AudioResampler进行重采样
播放线程分为两种情况:
- 硬解码播放线程OffloadThread不会对音频进行重采样
- 非硬解码使用MixerThread线程播放,将会对音频按照需要使用AudioMixer进行重采样,实际上AudioMixer也是调用AudioResampler进行重采样工作。
-
从AudioMixer提供的接口方法分析
主要作用是重采样,将各个音轨的数据混合在一起输出给音频设备
主要通过接收参数,执行相关操作,
参考路径:
frameworks/av/services/audioflinger/AudioMixer.h
参数设置接口:
setParameter(int name, int target, int param, void *value);
enum { // names // track names (MAX_NUM_TRACKS units) TRACK0 = 0x1000, // 0x2000 is unused // setParameter targets TRACK = 0x3000, RESAMPLE = 0x3001, RAMP_VOLUME = 0x3002, // ramp to new volume VOLUME = 0x3003, // don't ramp TIMESTRETCH = 0x3004, // set Parameter names // for target TRACK CHANNEL_MASK = 0x4000, FORMAT = 0x4001, MAIN_BUFFER = 0x4002, AUX_BUFFER = 0x4003, DOWNMIX_TYPE = 0X4004, MIXER_FORMAT = 0x4005, // AUDIO_FORMAT_PCM_(FLOAT|16_BIT) MIXER_CHANNEL_MASK = 0x4006, // Channel mask for mixer output // for target RESAMPLE SAMPLE_RATE = 0x4100, // Configure sample rate conversion on this track name; // parameter 'value' is the new sample rate in Hz. // Only creates a sample rate converter the first time that // the track sample rate is different from the mix sample rate. // If the new sample rate is the same as the mix sample rate, // and a sample rate converter already exists, // then the sample rate converter remains present but is a no-op. RESET = 0x4101, // Reset sample rate converter without changing sample rate. // This clears out the resampler's input buffer. REMOVE = 0x4102, // Remove the sample rate converter on this track name; // the track is restored to the mix sample rate. // for target RAMP_VOLUME and VOLUME (8 channels max) // FIXME use float for these 3 to improve the dynamic range VOLUME0 = 0x4200, VOLUME1 = 0x4201, AUXLEVEL = 0x4210, // for target TIMESTRETCH PLAYBACK_RATE = 0x4300, // Configure timestretch on this track name; // parameter 'value' is a pointer to the new playback rate. };
从AudioResampler提供的接口方法分析
从构造函数来看,就是根据不同的音质要求,创建不同的AudioResampler子类实例。如下枚举可见,重采样方法有三种插值方法
// Determines quality of SRC. // LOW_QUALITY: linear interpolator (1st order) // MED_QUALITY: cubic interpolator (3rd order) // HIGH_QUALITY: fixed multi-tap FIR (e.g. 48KHz->44.1KHz) // NOTE: high quality SRC will only be supported for // certain fixed rate conversions. Sample rate cannot be // changed dynamically. enum src_quality { DEFAULT_QUALITY=0, LOW_QUALITY=1, MED_QUALITY=2, HIGH_QUALITY=3, VERY_HIGH_QUALITY=4, DYN_LOW_QUALITY=5, DYN_MED_QUALITY=6, DYN_HIGH_QUALITY=7,#ifdef QTI_RESAMPLER QTI_QUALITY=8,#endif };
构造函数
AudioResampler* AudioResampler::create(audio_format_t format, int inChannelCount, int32_t sampleRate, src_quality quality) { bool atFinalQuality; if (quality == DEFAULT_QUALITY) { // read the resampler default quality property the first time it is needed int ok = pthread_once(&once_control, init_routine); if (ok != 0) { ALOGE("%s pthread_once failed: %d", __func__, ok); } quality = defaultQuality; atFinalQuality = false; } else { atFinalQuality = true; } /* if the caller requests DEFAULT_QUALITY and af.resampler.property * has not been set, the target resampler quality is set to DYN_MED_QUALITY, * and allowed to "throttle" down to DYN_LOW_QUALITY if necessary * due to estimated CPU load of having too many active resamplers * (the code below the if). */ if (quality == DEFAULT_QUALITY) { quality = DYN_MED_QUALITY; } // naive implementation of CPU load throttling doesn't account for whether resampler is active pthread_mutex_lock(&mutex); for (;;) { uint32_t deltaMHz = qualityMHz(quality); uint32_t newMHz = currentMHz + deltaMHz; if ((qualityIsSupported(quality) && newMHz <= maxMHz) || atFinalQuality) { ALOGV("resampler load %u -> %u MHz due to delta +%u MHz from quality %d", currentMHz, newMHz, deltaMHz, quality); currentMHz = newMHz; break; } // not enough CPU available for proposed quality level, so try next lowest level switch (quality) { default: case LOW_QUALITY: atFinalQuality = true; break; case MED_QUALITY: quality = LOW_QUALITY; break; case HIGH_QUALITY: quality = MED_QUALITY; break; case VERY_HIGH_QUALITY: quality = HIGH_QUALITY; break; case DYN_LOW_QUALITY: atFinalQuality = true; break; case DYN_MED_QUALITY: quality = DYN_LOW_QUALITY; break; case DYN_HIGH_QUALITY: quality = DYN_MED_QUALITY; break;#ifdef QTI_RESAMPLER case QTI_QUALITY: quality = DYN_HIGH_QUALITY; break;#endif } } pthread_mutex_unlock(&mutex); AudioResampler* resampler; switch (quality) { default: case LOW_QUALITY: ALOGV("Create linear Resampler"); LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT); resampler = new AudioResamplerOrder1(inChannelCount, sampleRate); break; case MED_QUALITY: ALOGV("Create cubic Resampler"); LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT); resampler = new AudioResamplerCubic(inChannelCount, sampleRate); break; case HIGH_QUALITY: ALOGV("Create HIGH_QUALITY sinc Resampler"); LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT); resampler = new AudioResamplerSinc(inChannelCount, sampleRate); break; case VERY_HIGH_QUALITY: ALOGV("Create VERY_HIGH_QUALITY sinc Resampler = %d", quality); LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT); resampler = new AudioResamplerSinc(inChannelCount, sampleRate, quality); break; case DYN_LOW_QUALITY: case DYN_MED_QUALITY: case DYN_HIGH_QUALITY: ALOGV("Create dynamic Resampler = %d", quality); if (format == AUDIO_FORMAT_PCM_FLOAT) { resampler = new AudioResamplerDyn<float, float, float>(inChannelCount, sampleRate, quality); } else { LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT); if (quality == DYN_HIGH_QUALITY) { resampler = new AudioResamplerDyn<int32_t, int16_t, int32_t>(inChannelCount, sampleRate, quality); } else { resampler = new AudioResamplerDyn<int16_t, int16_t, int32_t>(inChannelCount, sampleRate, quality); } } break;#ifdef QTI_RESAMPLER case QTI_QUALITY: ALOGV("Create QTI_QUALITY Resampler = %d",quality); resampler = new AudioResamplerQTI(format, inChannelCount, sampleRate); break;#endif } // initialize resampler resampler->init(); return resampler;}
之后将会从具体的播放与录音流程进行分析
多谢各位纠错!~
参考文章
http://blog.csdn.net/augusdi/article/details/12516337
http://blog.csdn.net/u010681466/article/details/50573440
- 【Android多媒体(重采样与混频)】重采样等基本概念
- 【Android多媒体(重采样与混频)】AudioResamper重采样算法分析
- 【Android多媒体(重采样与混频)】从录音流程分析AudioResampler
- 【Android多媒体(重采样与混频)】从playback流程分析AudioResampler,AudioMixer
- 重采样与重分类
- 重采样
- 重采样
- ANDROID音频系统散记之五:如何绕开多媒体音轨的重采样
- ANDROID音频系统散记之五:如何绕开多媒体音轨的重采样
- ANDROID音频系统散记之五:如何绕开多媒体音轨的重采样
- 音频重采样函数
- PCM,WAV 重采样
- 音频格式重采样。
- 影像金字塔重采样
- SPEEX重采样分析
- GDAL影像重采样
- 数字图像重采样检测
- D3D之多重采样
- Faster R-CNN学习笔记
- jqery ajax请求样例
- 堆栈的不同
- Spark 2.0系列之SparkSession详解
- Java集合--JDK 1.8 ConcurrentHashMap 源码剖析
- 【Android多媒体(重采样与混频)】重采样等基本概念
- Ubuntu16.04LTS下eclipse运行卡死等问题解决方法
- 使用mediacodec 解码AAC
- 拉格朗日乘子法的几何意义
- 如何定位一款产品?
- C语言--汉字逆置
- Okhttp连接https添加自产证书
- 腾讯社交广告高校算法大赛 baseline1
- 图论: 割点、桥(割边)、强连通分量 学习笔记