博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android Audio代码分析18 - setSampleRate函数
阅读量:6420 次
发布时间:2019-06-23

本文共 8891 字,大约阅读时间需要 29 分钟。

今天来看看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。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

转载地址:http://uclra.baihongyu.com/

你可能感兴趣的文章
Exception loading sessions from persistent storage (tomcat异常)
查看>>
直播疑难杂症排查(8)— 播放杂音、噪音、回声问题
查看>>
如何写gdb命令脚本
查看>>
Android ListView展示不同的布局
查看>>
iOS宏(自己使用,持续更新)
查看>>
手把手玩转win8开发系列课程(3)
查看>>
NGINX引入线程池 性能提升9倍
查看>>
《淘宝技术这十年》读书笔记 (四). 分布式时代和中间件
查看>>
linux下mongodb定时备份指定的集合
查看>>
oVirt JBAS server start failed, ajp proxy cann't server correct. ovirt-engine URL cann't open
查看>>
CDP WebConsole上线公告
查看>>
ubuntu下安装摄像头应用程序xawtv
查看>>
PostgreSQL 如何比较两个表的定义是否一致
查看>>
基于LNMP的Zabbbix之Zabbix Server源码详细安装,但不给图
查看>>
js 原型链(转)
查看>>
JPanel如何设置背景图片
查看>>
Ant's properties和datatypes
查看>>
表格列Column
查看>>
vi 常用的命令
查看>>
迅雷BoltUI
查看>>