Support audio-haptic coupled playback.
When trying to play with haptic channel mask, use adjust channels
buffer provider to make the haptic channel the same as the output one.
If haptic playback is supported, use adjust channel non destructive
buffer provider to output haptic data to the end of the sink buffer.
Otherwise, haptic data will be ignored.
Test: Manually
Bug: 111454766
Change-Id: Ic5f780de48c1e71de6ba5c4774d1ed2e9c8c51a0
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 365af75..2567b3b 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -136,6 +136,9 @@
// no initialization needed
// t->frameCount
+ t->mHapticChannelMask = channelMask & AUDIO_CHANNEL_HAPTIC_ALL;
+ t->mHapticChannelCount = audio_channel_count_from_out_mask(t->mHapticChannelMask);
+ channelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
t->channelCount = audio_channel_count_from_out_mask(channelMask);
t->enabled = false;
ALOGV_IF(audio_channel_mask_get_bits(channelMask) != AUDIO_CHANNEL_OUT_STEREO,
@@ -163,10 +166,13 @@
t->mMixerChannelCount = audio_channel_count_from_out_mask(t->mMixerChannelMask);
t->mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT;
// haptic
- t->mAdjustInChannelCount = 0;
- t->mAdjustOutChannelCount = 0;
- t->mAdjustNonDestructiveInChannelCount = 0;
- t->mAdjustNonDestructiveOutChannelCount = 0;
+ t->mHapticPlaybackEnabled = false;
+ t->mMixerHapticChannelMask = AUDIO_CHANNEL_NONE;
+ t->mMixerHapticChannelCount = 0;
+ t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount;
+ t->mAdjustOutChannelCount = t->channelCount + t->mMixerHapticChannelCount;
+ t->mAdjustNonDestructiveInChannelCount = t->mAdjustOutChannelCount;
+ t->mAdjustNonDestructiveOutChannelCount = t->channelCount;
t->mKeepContractedChannels = false;
// Check the downmixing (or upmixing) requirements.
status_t status = t->prepareForDownmix();
@@ -193,13 +199,20 @@
LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
const std::shared_ptr<Track> &track = mTracks[name];
- if (trackChannelMask == track->channelMask
- && mixerChannelMask == track->mMixerChannelMask) {
+ if (trackChannelMask == (track->channelMask | track->mHapticChannelMask)
+ && mixerChannelMask == (track->mMixerChannelMask | track->mMixerHapticChannelMask)) {
return false; // no need to change
}
+ const audio_channel_mask_t hapticChannelMask = trackChannelMask & AUDIO_CHANNEL_HAPTIC_ALL;
+ trackChannelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
+ const audio_channel_mask_t mixerHapticChannelMask = mixerChannelMask & AUDIO_CHANNEL_HAPTIC_ALL;
+ mixerChannelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
// always recompute for both channel masks even if only one has changed.
const uint32_t trackChannelCount = audio_channel_count_from_out_mask(trackChannelMask);
const uint32_t mixerChannelCount = audio_channel_count_from_out_mask(mixerChannelMask);
+ const uint32_t hapticChannelCount = audio_channel_count_from_out_mask(hapticChannelMask);
+ const uint32_t mixerHapticChannelCount =
+ audio_channel_count_from_out_mask(mixerHapticChannelMask);
ALOG_ASSERT((trackChannelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX)
&& trackChannelCount
@@ -208,6 +221,24 @@
track->channelCount = trackChannelCount;
track->mMixerChannelMask = mixerChannelMask;
track->mMixerChannelCount = mixerChannelCount;
+ track->mHapticChannelMask = hapticChannelMask;
+ track->mHapticChannelCount = hapticChannelCount;
+ track->mMixerHapticChannelMask = mixerHapticChannelMask;
+ track->mMixerHapticChannelCount = mixerHapticChannelCount;
+
+ if (track->mHapticChannelCount > 0) {
+ track->mAdjustInChannelCount = track->channelCount + track->mHapticChannelCount;
+ track->mAdjustOutChannelCount = track->channelCount + track->mMixerHapticChannelCount;
+ track->mAdjustNonDestructiveInChannelCount = track->mAdjustOutChannelCount;
+ track->mAdjustNonDestructiveOutChannelCount = track->channelCount;
+ track->mKeepContractedChannels = track->mHapticPlaybackEnabled;
+ } else {
+ track->mAdjustInChannelCount = 0;
+ track->mAdjustOutChannelCount = 0;
+ track->mAdjustNonDestructiveInChannelCount = 0;
+ track->mAdjustNonDestructiveOutChannelCount = 0;
+ track->mKeepContractedChannels = false;
+ }
// channel masks have changed, does this track need a downmixer?
// update to try using our desired format (if we aren't already using it)
@@ -616,7 +647,8 @@
case CHANNEL_MASK: {
const audio_channel_mask_t trackChannelMask =
static_cast<audio_channel_mask_t>(valueInt);
- if (setChannelMasks(name, trackChannelMask, track->mMixerChannelMask)) {
+ if (setChannelMasks(name, trackChannelMask,
+ (track->mMixerChannelMask | track->mMixerHapticChannelMask))) {
ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", trackChannelMask);
invalidate();
}
@@ -665,11 +697,21 @@
case MIXER_CHANNEL_MASK: {
const audio_channel_mask_t mixerChannelMask =
static_cast<audio_channel_mask_t>(valueInt);
- if (setChannelMasks(name, track->channelMask, mixerChannelMask)) {
+ if (setChannelMasks(name, track->channelMask | track->mHapticChannelMask,
+ mixerChannelMask)) {
ALOGV("setParameter(TRACK, MIXER_CHANNEL_MASK, %#x)", mixerChannelMask);
invalidate();
}
} break;
+ case HAPTIC_ENABLED: {
+ const bool hapticPlaybackEnabled = static_cast<bool>(valueInt);
+ if (track->mHapticPlaybackEnabled != hapticPlaybackEnabled) {
+ track->mHapticPlaybackEnabled = hapticPlaybackEnabled;
+ track->mKeepContractedChannels = hapticPlaybackEnabled;
+ track->prepareForAdjustChannelsNonDestructive(mFrameCount);
+ track->prepareForAdjustChannels();
+ }
+ } break;
default:
LOG_ALWAYS_FATAL("setParameter track: bad param %d", param);
}
@@ -1359,8 +1401,8 @@
const std::shared_ptr<Track> &t = mTracks[group[0]];
memset(t->mainBuffer, 0,
- mFrameCount * t->mMixerChannelCount
- * audio_bytes_per_sample(t->mMixerFormat));
+ mFrameCount * audio_bytes_per_frame(
+ t->mMixerChannelCount + t->mMixerHapticChannelCount, t->mMixerFormat));
// now consume data
for (const int name : group) {