[RK3288][Android6.0] Audio中的录音重采样小结

Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92

Android自带录音apk使用的采样率是8kHz,而硬件录音的采样率是44.1kHz,所以需要做重采样。
HAL层重采样
hardware/rockchip/audio/tinyalsa_hal/audio_hw.c
static int adev_open_input_stream(......)
{
......
    //requested_rate: app申请的采样率
    //pcm_config->rate: 硬件实际采样率
    if (in->requested_rate != pcm_config->rate) {
        in->buf_provider.get_next_buffer = get_next_buffer;
        in->buf_provider.release_buffer = release_buffer;
......
        ret = create_resampler(pcm_config->rate,
                               in->requested_rate,
                               audio_channel_count_from_in_mask(in->channel_mask),
                               RESAMPLER_QUALITY_DEFAULT,
                               &in->buf_provider,
                               &in->resampler);
......
    }
......
}
重采样算法用android自带库
system/media/audio_utils/resampler.c
int create_resampler(......)
{
......
    rsmp->speex_resampler = speex_resampler_init(channelCount,
                                      inSampleRate,
                                      outSampleRate,
                                      quality,
                                      &error);
......
}
本质上用的是speex开源库
external/speex/libspeex/resample.c
EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
{
   return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
}
speex使用的是cubic插值算法:
There is one main difference, though. This resampler uses cubic
interpolation instead of linear interpolation in the above paper. This
makes the table much smaller and makes it possible to compute that table
on a per-stream basis. In turn, being able to tweak the table for each
stream makes it possible to both reduce complexity on simple ratios
(e.g. 2/3), and get rid of the rounding operations in the inner loop.
The latter both reduces CPU time and makes the algorithm more SIMD-friendly.

Framework重采样
Android自身有录音重采样算法。
openRecord -> AudioFlinger.cpp
    thread->createRecordTrack_l ->
        new RecordTrack ->
            new RecordBufferConverter ->
                updateParameters
status_t AudioFlinger::RecordThread::RecordBufferConverter::updateParameters(......)
{
......
    //mSrcSampleRate: 从HAL层获取,下面再看
    //mDstSampleRate: APP设置的采样率
    if (mSrcSampleRate != mDstSampleRate) {
        mResampler = AudioResampler::create(AUDIO_FORMAT_PCM_FLOAT,
                mSrcChannelCount, mDstSampleRate);
        mResampler->setSampleRate(mSrcSampleRate);
        mResampler->setVolume(AudioMixer::UNITY_GAIN_FLOAT, AudioMixer::UNITY_GAIN_FLOAT);
    }
......
}
AudioResampler* AudioResampler::create(audio_format_t format, int inChannelCount,
        int32_t sampleRate, src_quality quality) {
......
    //根据不同的quality选择不同的采样算法
    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:
......
            resampler = new AudioResamplerDyn<float, float, float>(inChannelCount,
......
}
mSrcSampleRate的来源:
Threads.cpp
void AudioFlinger::RecordThread::readInputParameters_l()
{
    mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
......
}
最终来自audio_hw.c
static uint32_t in_get_sample_rate(const struct audio_stream *stream)
{
    struct stream_in *in = (struct stream_in *)stream;
    //ALOGV("%s:get requested_rate : %d ",__FUNCTION__,in->requested_rate);
    return in->requested_rate;
}
而requested_rate就是从上层app传下来的需要设置的采样率,因此mSrcSampleRate和mDstSampleRate一样,在framework不会做重采样。

Android官方对framework采样率的说明:


各个算法的区别


参考
重采样:
https://source.android.com/devices/audio/src
插值算法不同:
https://graphicdesign.stackexchange.com/questions/26385/difference-between-none-linear-cubic-and-sinclanczos3-interpolation-in-image
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页