Next let's take a look at the interfaces related to volume settings.
**************************************** * Source Code ************************************** ***********
// Test case 1: setStereoVolume () with max volume returns SUCCESS
@ LargeTest
Public void testSetStereoVolumeMax () throws Exception {
// Constants for test
Final String TEST_NAME = "testSetStereoVolumeMax ";
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];
// -------- Test --------------
Track. write (data, 0, data. length );
Track. write (data, 0, data. length );
Track. play ();
Float maxVol = AudioTrack. getMaxVolume ();
AssertTrue (TEST_NAME, track. setStereoVolume (maxVol, maxVol) = AudioTrack. SUCCESS );
// -------- Tear down --------------
Track. release ();
}
**************************************** **************************************** **************
Source code path:
Frameworks \ base \ media \ tests \ mediaframeworktest \ src \ com \ android \ mediaframeworktest \ functional \ MediaAudioTrackTest. java
################ ################
// Test case 1: setStereoVolume () with max volume returns SUCCESS
@ LargeTest
Public void testSetStereoVolumeMax () throws Exception {
// Constants for test
Final String TEST_NAME = "testSetStereoVolumeMax ";
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];
// -------- Test --------------
Track. write (data, 0, data. length );
Track. write (data, 0, data. length );
Track. play ();
Float maxVol = AudioTrack. getMaxVolume ();
++ GetMaxVolume ++ ++
/**
* Returns the maximum valid volume value. Volume values set above this one will
* Be clamped at this value.
* @ Return the maximum volume expressed as a linear attenuation.
*/
Static public float getMaxVolume (){
Return AudioTrack. VOLUME_MAX;
}
------------------------------ GetMaxVolume ----------------------------------
AssertTrue (TEST_NAME, track. setStereoVolume (maxVol, maxVol) = AudioTrack. SUCCESS );
++ SetStereoVolume ++ ++
/**
* Sets the specified left/right output volume values on the AudioTrack. Values are clamped
* To the ({@ link # getMinVolume ()}, {@ link # getMaxVolume ()}) interval if outside this range.
* @ Param leftVolume output attenuation for the left channel. A value of 0.0f is silence,
* A value of 1.0f is no attenuation.
* @ Param rightVolume output attenuation for the right channel
* @ Return error code or success, see {@ link # SUCCESS },
* {@ Link # ERROR_INVALID_OPERATION}
*/
Public int setStereoVolume (float leftVolume, float rightVolume ){
If (mState! = STATE_INITIALIZED ){
Return ERROR_INVALID_OPERATION;
}
// Ensure that the volume is within the range of [min, max.
// Clamp the volumes
If (leftVolume <getMinVolume ()){
LeftVolume = getMinVolume ();
}
If (leftVolume> getMaxVolume ()){
LeftVolume = getMaxVolume ();
}
If (rightVolume <getMinVolume ()){
RightVolume = getMinVolume ();
}
If (rightVolume> getMaxVolume ()){
RightVolume = getMaxVolume ();
}
Native_setVolume (leftVolume, rightVolume );
++ Android_media_AudioTrack_set_volume ++ ++
Static void
Android_media_AudioTrack_set_volume (JNIEnv * env, jobject thiz, jfloat leftVol, jfloat rightVol)
{
AudioTrack * lpTrack = (AudioTrack *) env-> GetIntField (
Thiz, javaAudioTrackFields. nativeTrackInJavaObj );
If (lpTrack = NULL ){
JniThrowException (env, "java/lang/IllegalStateException ",
"Unable to retrieve AudioTrack pointer for setVolume ()");
Return;
}
LpTrack-> setVolume (leftVol, rightVol );
++ AudioTrack :: setVolume ++
Status_t AudioTrack: setVolume (float left, float right)
{
// Check the range
If (left> 1.0f | right> 1.0f ){
Return BAD_VALUE;
}
// Save the volume to the member variable
// The AudioTrack: set class initializes these two volumes to 1.0f.
// The AudioTrack: getVolume function extracts the two volume values.
// The AudioTrack: createTrack function assigns these two values to mCblk-> volumeLR.
MVolume [LEFT] = left;
MVolume [RIGHT] = right;
// Write must be atomic
// According to the definition of audio_track_cblk_t, volume information is actually a union, which is stored as volumeLR,
// It is actually used as the uint16_t volume [2] array.
++ Union ++ ++
Volatile union {
Uint16_t volume [2];
Uint32_t volumeLR;
};
----------------------------- Union -----------------------------------
// In the AudioMixer class, when you copy data from audio_track_cblk_t to the main buffer, the data is processed according to the volume.
// As shown in the previous process _ OneTrack16BitsStereoNoResampling function.
MCblk-> volumeLR = (uint32_t (uint16_t (right * 0x1000) <16) | uint16_t (left * 0x1000 );
Return NO_ERROR;
}
----------------------------- AudioTrack: setVolume ----------------------------------
}
---------------------------- Android_media_AudioTrack_set_volume ------------------------------------
Return SUCCESS;
}
------------------------------ SetStereoVolume ----------------------------------
// -------- Tear down --------------
Track. release ();
}
######################################## ###################
& Summary &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&
The setStereoVolume function finally sets the soft volume.
When you copy data from audio_track_cblk_t to the main buffer in the AudioMixer class, the volume is used to process the data.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&
From: Jiangfeng's column