Android Audio Code Analysis 18-setSampleRate Function

Source: Internet
Author: User

Let's take a look at the playback rate related interfaces today. Including set and get.


**************************************** * Source Code ************************************** ***********
// 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 = 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 ();
}
**************************************** **************************************** **************
Source code path:
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 = 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 ()
{
// The sample rate in audio_track_cblk_t is returned directly.
// The audio_track_cblk_t object is created in the constructor AudioFlinger: ThreadBase: TrackBase: new (mCblk) audio_track_cblk_t ();
// After the audio_track_cblk_t object is created, the member variable sampleRate is assigned a value: mCblk-> sampleRate = sampleRate;
// Here sampleRate is actually the sampleRate passed in when the AudioTrack object is created.
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
* Content. Setting it to half the sample rate of the content will cause the playback
* 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
* {@ 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}
*/
// Check out the comment.
// The rate changed here is only the rate during playback, not the data rate.
// For example, if you set the rate to half of the original one, the playback time will be doubled.
// The set rate ranges from 1Hz to 2 times of the original rate.
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 ++
// Feel so familiar!
// I have seen it many times!
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 ();
// The AudioSystem: AudioFlingerClient: ioConfigChanged function adds a member to 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
{
// The function AudioFlinger: PlaybackThread: readOutputParameters will assign 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;


// Set the rate to the audio_track_cblk_t object.
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 ();
}
######################################## ###################


& Summary &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&
Set rate only changes the rate during playback, rather than the data rate.
That is to say, if the set rate is different from the original rate, the playing time will change.
In the AudioFlinger: MixerThread: threadLoop function, max period is calculated based on the rate.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&

From: Jiangfeng's column

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.