`
mmdev
  • 浏览: 12932875 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

Android Audio代码分析18 - setSampleRate函数

 
阅读更多
今天来看看playback rate相关的接口。包括set和get。


*****************************************源码*************************************************
    //Test case 6: setPlaybackRate() accepts values twice the output sample rate
    @LargeTest
    public void testSetPlaybackRateTwiceOutputSR() throws Exception {
        // constants for test
        final String TEST_NAME = "testSetPlaybackRateTwiceOutputSR";
        final int TEST_SR = 22050;
        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
        final int TEST_MODE = AudioTrack.MODE_STREAM;
        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
        
        //-------- initialization --------------
        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
                minBuffSize, TEST_MODE);
        byte data[] = new byte[minBuffSize/2];
        int outputSR = AudioTrack.getNativeOutputSampleRate(TEST_STREAM_TYPE);
        //--------    test        --------------
        track.write(data, 0, data.length);
        track.write(data, 0, data.length);
        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
        track.play();
        assertTrue(TEST_NAME, track.setPlaybackRate(2*outputSR) == AudioTrack.SUCCESS);
        //-------- tear down      --------------
        track.release();
    }

**********************************************************************************************
源码路径:
frameworks\base\media\tests\mediaframeworktest\src\com\android\mediaframeworktest\functional\MediaAudioTrackTest.java


#######################说明################################
    //Test case 6: setPlaybackRate() accepts values twice the output sample rate
    @LargeTest
    public void testSetPlaybackRateTwiceOutputSR() throws Exception {
        // constants for test
        final String TEST_NAME = "testSetPlaybackRateTwiceOutputSR";
        final int TEST_SR = 22050;
        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
        final int TEST_MODE = AudioTrack.MODE_STREAM;
        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
        
        //-------- initialization --------------
        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
                minBuffSize, TEST_MODE);
        byte data[] = new byte[minBuffSize/2];
        int outputSR = AudioTrack.getNativeOutputSampleRate(TEST_STREAM_TYPE);
// +++++++++++++++++++++++++++++getNativeOutputSampleRate+++++++++++++++++++++++++++++++++++
    /**
     *  Returns the hardware output sample rate
     */
    static public int getNativeOutputSampleRate(int streamType) {
        return native_get_output_sample_rate(streamType);
// +++++++++++++++++++++++++++++android_media_AudioTrack_get_playback_rate+++++++++++++++++++++++++++++++++++
static jint android_media_AudioTrack_get_playback_rate(JNIEnv *env,  jobject thiz) {
    AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
                thiz, javaAudioTrackFields.nativeTrackInJavaObj);


    if (lpTrack) {
        return (jint) lpTrack->getSampleRate();   
// ++++++++++++++++++++++++++++AudioTrack::getSampleRate++++++++++++++++++++++++++++++++++++
uint32_t AudioTrack::getSampleRate()
{
// 直接返回了audio_track_cblk_t中的sample rate。
// audio_track_cblk_t对象在AudioFlinger::ThreadBase::TrackBase::TrackBase的构造函数中被创建:new(mCblk) audio_track_cblk_t();
// 创建audio_track_cblk_t对象后,即对其成员变量sampleRate进行了赋值:mCblk->sampleRate = sampleRate;
// 此处的sampleRate其实是创建AudioTrack对象时传入的sampleRate。
    return mCblk->sampleRate;
}
// ----------------------------AudioTrack::getSampleRate------------------------------------
    } else {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioTrack pointer for getSampleRate()");
        return AUDIOTRACK_ERROR;
    }
}
// -----------------------------android_media_AudioTrack_get_playback_rate-----------------------------------
    }
// -----------------------------getNativeOutputSampleRate-----------------------------------
        //--------    test        --------------
        track.write(data, 0, data.length);
        track.write(data, 0, data.length);
        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
        track.play();
        assertTrue(TEST_NAME, track.setPlaybackRate(2*outputSR) == AudioTrack.SUCCESS);
// ++++++++++++++++++++++++++++setPlaybackRate+++++++++++++++++++++++++++++++++++
    /**
     * Sets the playback sample rate for this track. This sets the sampling rate at which
     * the audio data will be consumed and played back, not the original sampling rate of the
     * content. Setting it to half the sample rate of the content will cause the playback to
     * last twice as long, but will also result in a negative pitch shift.
     * The valid sample rate range if from 1Hz to twice the value returned by
     * {@link #getNativeOutputSampleRate(int)}.
     * @param sampleRateInHz the sample rate expressed in Hz
     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
     *    {@link #ERROR_INVALID_OPERATION}
     */
// 看看这段注释
// 此处改变的rate,只是播放时的rate,并不是数据本身的rate。
// 例如,如果将rate设置为原来的一半,则播放时间将变为原来的2倍。
// 所设rate的范围是1Hz到原来rate的2倍。
    public int setPlaybackRate(int sampleRateInHz) {
        if (mState != STATE_INITIALIZED) {
            return ERROR_INVALID_OPERATION;
        }
        if (sampleRateInHz <= 0) {
            return ERROR_BAD_VALUE;
        }
        return native_set_playback_rate(sampleRateInHz);
// ++++++++++++++++++++++++++++android_media_AudioTrack_set_playback_rate++++++++++++++++++++++++++++++++++++
static jint android_media_AudioTrack_set_playback_rate(JNIEnv *env,  jobject thiz,
        jint sampleRateInHz) {
    AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
                thiz, javaAudioTrackFields.nativeTrackInJavaObj);


    if (lpTrack) {
        return android_media_translateErrorCode(lpTrack->setSampleRate(sampleRateInHz));
// +++++++++++++++++++++++++++AudioTrack::setSampleRate+++++++++++++++++++++++++++++++++++++
status_t AudioTrack::setSampleRate(int rate)
{
    int afSamplingRate;


    if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) {
        return NO_INIT;
// +++++++++++++++++++++++++++++AudioSystem::getOutputSamplingRate+++++++++++++++++++++++++++++++++++
// 感觉这么熟悉!
// 原来已见过多次!
status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType)
{
    OutputDescriptor *outputDesc;
    audio_io_handle_t output;


    if (streamType == DEFAULT) {
        streamType = MUSIC;
    }


    output = getOutput((stream_type)streamType);
    if (output == 0) {
        return PERMISSION_DENIED;
    }


    gLock.lock();
// AudioSystem::AudioFlingerClient::ioConfigChanged函数有往gOutputs中添加成员
    outputDesc = AudioSystem::gOutputs.valueFor(output);
    if (outputDesc == 0) {
        LOGV("getOutputSamplingRate() no output descriptor for output %d in gOutputs", output);
        gLock.unlock();
        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
        if (af == 0) return PERMISSION_DENIED;
        *samplingRate = af->sampleRate(output);
// +++++++++++++++++++++++++AudioFlinger::sampleRate+++++++++++++++++++++++++++++++++++++++
uint32_t AudioFlinger::sampleRate(int output) const
{
    Mutex::Autolock _l(mLock);
    PlaybackThread *thread = checkPlaybackThread_l(output);
    if (thread == NULL) {
        LOGW("sampleRate() unknown thread %d", output);
        return 0;
    }
    return thread->sampleRate();
// +++++++++++++++++++++++++++AudioFlinger::ThreadBase::sampleRate+++++++++++++++++++++++++++++++++++++
uint32_t AudioFlinger::ThreadBase::sampleRate() const
{
// 函数AudioFlinger::PlaybackThread::readOutputParameters中会给mSampleRate赋值: mSampleRate = mOutput->sampleRate();
    return mSampleRate;
}
// ---------------------------AudioFlinger::ThreadBase::sampleRate-------------------------------------
}
// -------------------------AudioFlinger::sampleRate---------------------------------------
    } else {
        LOGV("getOutputSamplingRate() reading from output desc");
        *samplingRate = outputDesc->samplingRate;
        gLock.unlock();
    }


    LOGV("getOutputSamplingRate() streamType %d, output %d, sampling rate %d", streamType, output, *samplingRate);


    return NO_ERROR;
}
// -----------------------------AudioSystem::getOutputSamplingRate-----------------------------------
    }
    // Resampler implementation limits input sampling rate to 2 x output sampling rate.
    if (rate <= 0 || rate > afSamplingRate*2 ) return BAD_VALUE;


// 将rate设置到audio_track_cblk_t对象中
    mCblk->sampleRate = rate;
    return NO_ERROR;
}
// ---------------------------AudioTrack::setSampleRate-------------------------------------
    } else {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioTrack pointer for setSampleRate()");
        return AUDIOTRACK_ERROR;
    }
}
// ----------------------------android_media_AudioTrack_set_playback_rate------------------------------------
    }
// ----------------------------setPlaybackRate------------------------------------
        //-------- tear down      --------------
        track.release();
    }

###########################################################


&&&&&&&&&&&&&&&&&&&&&&&总结&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
set rate改变的只是播放时的rate,而不是数据本身的rate。
也就是说,set rate若与原来的rate不同的话,播放时间会改变。
函数AudioFlinger::MixerThread::threadLoop中会根据rate计算max period。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics