【Android多媒体(重采样与混频)】重采样等基本概念

重采样和混频的概念

关于音频采样,百度上面找到这样的解答:

频率对应于时间轴线,振幅对应于电平轴线。波是无限光滑的,弦线可以看成由无数点组成,由于存储空间是相对有限的,数字编码过程中,必须对弦线的点进行采样。采样的过程就是抽取某点的频率值,很显然,在一秒中内抽取的点越多,获取得频率信息更丰富,为了复原波形,一次振动中,必须有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(inChannelCount,
                        sampleRate, quality);
            } else {
                resampler = new AudioResamplerDyn(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

你可能感兴趣的:(多媒体技术)