Volume control for bit-perfect thread.
When there is a track play bit-perfectly, the framework will no longer
apply software volume control in the mixer. In that case, the audio
framework need to send the volume command down to the HAL.
Bug: 262578034
Test: adjust volume while play bit-perfectly
Change-Id: I927a9bd20b7fcce841a133c2786bdc4b352afa30
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index c2b82d1..6a39108 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -116,6 +116,9 @@
track->mKeepContractedChannels = false;
}
+ track->mInputFrameSize = audio_bytes_per_frame(
+ track->channelCount + track->mHapticChannelCount, track->mFormat);
+
// channel masks have changed, does this track need a downmixer?
// update to try using our desired format (if we aren't already using it)
const status_t status = track->prepareForDownmix();
@@ -309,9 +312,8 @@
ALOGV("AudioMixer::%s(%p) teeBuffer=%p", __func__, this, teeBuffer);
unprepareForTee();
if (teeBuffer != nullptr) {
- const size_t frameSize = audio_bytes_per_frame(channelCount + mHapticChannelCount, mFormat);
mTeeBufferProvider.reset(new TeeBufferProvider(
- frameSize, frameSize, kCopyBufferFrameCount,
+ mInputFrameSize, mInputFrameSize, kCopyBufferFrameCount,
(uint8_t*)teeBuffer, mTeeBufferFrameCount));
reconfigureBufferProviders();
}
@@ -590,6 +592,8 @@
t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount;
t->mAdjustOutChannelCount = t->channelCount;
t->mKeepContractedChannels = false;
+ t->mInputFrameSize = audio_bytes_per_frame(
+ t->channelCount + t->mHapticChannelCount, t->mFormat);
// Check the downmixing (or upmixing) requirements.
status_t status = t->prepareForDownmix();
if (status != OK) {
@@ -641,6 +645,10 @@
}
break;
}
+ if (t->teeBuffer != nullptr && t->volumeRL == 0) {
+ // Need to mute tee
+ memset(t->teeBuffer, 0, t->mTeeBufferFrameCount * t->mInputFrameSize);
+ }
}
}
}
diff --git a/media/libaudioprocessing/AudioMixerBase.cpp b/media/libaudioprocessing/AudioMixerBase.cpp
index fd06991..427bd55 100644
--- a/media/libaudioprocessing/AudioMixerBase.cpp
+++ b/media/libaudioprocessing/AudioMixerBase.cpp
@@ -152,6 +152,7 @@
AUDIO_CHANNEL_REPRESENTATION_POSITION, AUDIO_CHANNEL_OUT_STEREO);
t->mMixerChannelCount = audio_channel_count_from_out_mask(t->mMixerChannelMask);
t->mTeeBufferFrameCount = 0;
+ t->mInputFrameSize = audio_bytes_per_frame(t->channelCount, t->mFormat);
status_t status = postCreateTrack(t.get());
if (status != OK) return status;
mTracks[name] = t;
@@ -178,6 +179,7 @@
track->channelCount = trackChannelCount;
track->mMixerChannelMask = mixerChannelMask;
track->mMixerChannelCount = mixerChannelCount;
+ track->mInputFrameSize = audio_bytes_per_frame(track->channelCount, track->mFormat);
// Resampler channels may have changed.
track->recreateResampler(mSampleRate);
diff --git a/media/libaudioprocessing/include/media/AudioMixerBase.h b/media/libaudioprocessing/include/media/AudioMixerBase.h
index caccb6a..4bd85d8 100644
--- a/media/libaudioprocessing/include/media/AudioMixerBase.h
+++ b/media/libaudioprocessing/include/media/AudioMixerBase.h
@@ -297,6 +297,8 @@
int32_t mTeeBufferFrameCount;
+ uint32_t mInputFrameSize; // The track input frame size, used for tee buffer
+
protected:
// hooks
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index ebbdf56..9560609 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -148,8 +148,12 @@
sp<media::VolumeHandler> getVolumeHandler() { return mVolumeHandler; }
/** Set the computed normalized final volume of the track.
* !masterMute * masterVolume * streamVolume * averageLRVolume */
- void setFinalVolume(float volume);
+ void setFinalVolume(float volumeLeft, float volumeRight);
float getFinalVolume() const { return mFinalVolume; }
+ void getFinalVolume(float* left, float* right) const {
+ *left = mFinalVolumeLeft;
+ *right = mFinalVolumeRight;
+ }
using SourceMetadatas = std::vector<playback_track_metadata_v7_t>;
using MetadataInserter = std::back_insert_iterator<SourceMetadatas>;
@@ -355,6 +359,10 @@
// 'volatile' means accessed without lock or
// barrier, but is read/written atomically
float mFinalVolume; // combine master volume, stream type volume and track volume
+ float mFinalVolumeLeft; // combine master volume, stream type volume and track
+ // volume
+ float mFinalVolumeRight; // combine master volume, stream type volume and track
+ // volume
sp<AudioTrackServerProxy> mAudioTrackServerProxy;
bool mResumeToStopping; // track was paused in stopping state.
bool mFlushHwPending; // track requests for thread flush
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index f917527..2a58e46 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -5513,7 +5513,7 @@
vlf *= volume;
vrf *= volume;
- track->setFinalVolume((vlf + vrf) / 2.f);
+ track->setFinalVolume(vlf, vrf);
++fastTracks;
} else {
// was it previously active?
@@ -5712,7 +5712,7 @@
vaf = v * sendLevel * (1. / MAX_GAIN_INT);
}
- track->setFinalVolume((vrf + vlf) / 2.f);
+ track->setFinalVolume(vrf, vlf);
// Delegate volume control to effect in track effect chain if needed
if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
@@ -6320,7 +6320,7 @@
shaperVolume == 0.f});
if (lastTrack) {
- track->setFinalVolume((left + right) / 2.f);
+ track->setFinalVolume(left, right);
if (left != mLeftVolFloat || right != mRightVolFloat) {
mLeftVolFloat = left;
mRightVolFloat = right;
@@ -10804,6 +10804,8 @@
Vector<sp<Track>> *tracksToRemove) {
mixer_state result = MixerThread::prepareTracks_l(tracksToRemove);
// If there is only one active track and it is bit-perfect, enable tee buffer.
+ float volumeLeft = 1.0f;
+ float volumeRight = 1.0f;
if (mActiveTracks.size() == 1 && mActiveTracks[0]->isBitPerfect()) {
const int trackId = mActiveTracks[0]->id();
mAudioMixer->setParameter(
@@ -10811,6 +10813,7 @@
mAudioMixer->setParameter(
trackId, AudioMixer::TRACK, AudioMixer::TEE_BUFFER_FRAME_COUNT,
(void *)(uintptr_t)mNormalFrameCount);
+ mActiveTracks[0]->getFinalVolume(&volumeLeft, &volumeRight);
mIsBitPerfect = true;
} else {
mIsBitPerfect = false;
@@ -10822,6 +10825,11 @@
trackId, AudioMixer::TRACK, AudioMixer::TEE_BUFFER, nullptr);
}
}
+ if (mVolumeLeft != volumeLeft || mVolumeRight != volumeRight) {
+ mVolumeLeft = volumeLeft;
+ mVolumeRight = volumeRight;
+ setVolumeForOutput_l(volumeLeft, volumeRight);
+ }
return result;
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index f1b82e4..a319eab 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -2295,4 +2295,6 @@
private:
bool mIsBitPerfect;
+ float mVolumeLeft = 0.f;
+ float mVolumeRight = 0.f;
};
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 950d555..53917a8 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1401,8 +1401,11 @@
return mVolumeHandler->getVolumeShaperState(id);
}
-void AudioFlinger::PlaybackThread::Track::setFinalVolume(float volume)
+void AudioFlinger::PlaybackThread::Track::setFinalVolume(float volumeLeft, float volumeRight)
{
+ mFinalVolumeLeft = volumeLeft;
+ mFinalVolumeRight = volumeRight;
+ const float volume = (volumeLeft + volumeRight) * 0.5f;
if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
mFinalVolume = volume;
setMetadataHasChanged();