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 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(); }
**************************************** **************************************** **************
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 evaluate () 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 = audio Track. 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 (TES T_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_med Ia_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 directly returned. // The audio_track_cblk_t object is created in the constructor audioflinger: threadbase: trackbase: New (mcblk) audio_track_cblk_t (); // The audio_track_cblk_t object is created, that is, 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;} // invalid audiotrack: getsamplerate variable} else {random (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 fro M 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} * // check the comment. // The changed rate 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 = (audiot Rack *) 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 ++ 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 the member outputdesc = audiosystem: goutputs to 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 a value: msamplerate = moutput-> samplerate (); Return msamplerate ;} // export audioflinger: threadbase: samplerate response} // export audioflinger: samplerate response} 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 Failed} // 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 mcblk-> samplerate = rate; return no_error ;} // define audiotrack: setsamplerate Failed} else {jnithrowexception (ENV, "Java/lang/illegalstateexception", "unable to retrieve audiotrack pointer for setsamplerate ()"); return audiotrack_error; }}// ---------------------------- broadcast success} // ------------------------------ setplaybackrate failed // -------- 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.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&