audio: Add playback rate parameters to IStreamOut
Playback rate parameters allow changing the playback speed
of audio streams optionally preserving the pitch (this is
often referred to as "timestretch"). HALs can apply these
parameters when decoding of streams is done in hardware.
Bug: 133526565
Test: atest VtsHalAudioV6_0TargetTest
Change-Id: Ie78cd924bd034b57bf5b6a74affd62641ffc0aba
diff --git a/audio/6.0/IStreamOut.hal b/audio/6.0/IStreamOut.hal
index 91668ba..13a86ec 100644
--- a/audio/6.0/IStreamOut.hal
+++ b/audio/6.0/IStreamOut.hal
@@ -333,4 +333,33 @@
* @return retval operation completion status.
*/
setAudioDescriptionMixLevel(float leveldB) generates (Result retval);
+
+ /**
+ * Retrieves current playback rate parameters.
+ *
+ * Optional method
+ *
+ * @return retval operation completion status.
+ * @return playbackRate current playback parameters
+ */
+ getPlaybackRateParameters()
+ generates (Result retval, PlaybackRate playbackRate);
+
+ /**
+ * Sets the playback rate parameters that control playback behavior.
+ * This is normally used when playing encoded content and decoding
+ * is performed in hardware. Otherwise, the framework can apply
+ * necessary transformations.
+ *
+ * Optional method
+ *
+ * If the HAL supports setting the playback rate, it is recommended
+ * to support speed and pitch values at least in the range
+ * from 0.5f to 2.0f, inclusive (see the definition of PlaybackRate struct).
+ *
+ * @param playbackRate playback parameters
+ * @return retval operation completion status.
+ */
+ setPlaybackRateParameters(PlaybackRate playbackRate)
+ generates (Result retval);
};
diff --git a/audio/6.0/types.hal b/audio/6.0/types.hal
index efc3ea5..8ff618e 100644
--- a/audio/6.0/types.hal
+++ b/audio/6.0/types.hal
@@ -297,3 +297,61 @@
*/
RR = 3,
};
+
+/**
+ * Algorithms used for timestretching (preserving pitch while playing audio
+ * content at different speed).
+ */
+@export(name="audio_timestretch_stretch_mode_t", value_prefix="AUDIO_TIMESTRETCH_STRETCH_")
+enum TimestretchMode : int32_t {
+ // Need to be in sync with AUDIO_STRETCH_MODE_* constants in
+ // frameworks/base/media/java/android/media/PlaybackParams.java
+ DEFAULT = 0,
+ /** Selects timestretch algorithm best suitable for voice (speech) content. */
+ VOICE = 1,
+};
+
+/**
+ * Behavior when the values for speed and / or pitch are out
+ * of applicable range.
+ */
+@export(name="audio_timestretch_fallback_mode_t", value_prefix="AUDIO_TIMESTRETCH_FALLBACK_")
+enum TimestretchFallbackMode : int32_t {
+ // Need to be in sync with AUDIO_FALLBACK_MODE_* constants in
+ // frameworks/base/media/java/android/media/PlaybackParams.java
+ /** Play silence for parameter values that are out of range. */
+ MUTE = 1,
+ /** Return an error while trying to set the parameters. */
+ FAIL = 2,
+};
+
+/**
+ * Parameters determining playback behavior. They are used to speed up or
+ * slow down playback and / or change the tonal frequency of the audio content
+ * (pitch).
+ */
+struct PlaybackRate {
+ /**
+ * Speed factor (multiplier). Normal speed has the value of 1.0f.
+ * Values less than 1.0f slow down playback, value greater than 1.0f
+ * speed it up.
+ */
+ float speed;
+ /**
+ * Pitch factor (multiplier). Setting pitch value to 1.0f together
+ * with changing playback speed preserves the pitch, this is often
+ * called "timestretching." Setting the pitch value equal to speed produces
+ * the same effect as playing audio content at different sampling rate.
+ */
+ float pitch;
+ /**
+ * Selects the algorithm used for timestretching (preserving pitch while
+ * playing audio at different speed).
+ */
+ TimestretchMode timestretchMode;
+ /**
+ * Selects the behavior when the specified values for speed and / or pitch
+ * are out of applicable range.
+ */
+ TimestretchFallbackMode fallbackMode;
+};
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index cfbee34..7a4d72b 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -600,6 +600,18 @@
Return<Result> StreamOut::setAudioDescriptionMixLevel(float /*leveldB*/) {
return Result::NOT_SUPPORTED;
}
+
+Return<void> StreamOut::getPlaybackRateParameters(getPlaybackRateParameters_cb _hidl_cb) {
+ _hidl_cb(Result::NOT_SUPPORTED,
+ // Same as AUDIO_PLAYBACK_RATE_INITIALIZER
+ PlaybackRate{1.0f, 1.0f, TimestretchMode::DEFAULT, TimestretchFallbackMode::FAIL});
+ return Void();
+}
+
+Return<Result> StreamOut::setPlaybackRateParameters(const PlaybackRate& /*playbackRate*/) {
+ return Result::NOT_SUPPORTED;
+}
+
#endif
} // namespace implementation
diff --git a/audio/core/all-versions/default/include/core/default/StreamOut.h b/audio/core/all-versions/default/include/core/default/StreamOut.h
index 294867c..5db8626 100644
--- a/audio/core/all-versions/default/include/core/default/StreamOut.h
+++ b/audio/core/all-versions/default/include/core/default/StreamOut.h
@@ -126,6 +126,8 @@
Return<Result> setDualMonoMode(DualMonoMode mode) override;
Return<void> getAudioDescriptionMixLevel(getAudioDescriptionMixLevel_cb _hidl_cb) override;
Return<Result> setAudioDescriptionMixLevel(float leveldB) override;
+ Return<void> getPlaybackRateParameters(getPlaybackRateParameters_cb _hidl_cb) override;
+ Return<Result> setPlaybackRateParameters(const PlaybackRate& playbackRate) override;
#endif
static Result getPresentationPositionImpl(audio_stream_out_t* stream, uint64_t* frames,
diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
index c9ba509..9e2a050 100644
--- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
@@ -217,3 +217,37 @@
INSTANTIATE_TEST_CASE_P(AudioDescriptionMixLevelHidl, AudioDescriptionMixLevelHidlTest,
::testing::ValuesIn(getOutputDeviceConfigParameters()),
&DeviceConfigParameterToString);
+
+using PlaybackRateParametersHidlTest = AccessorHidlTest<PlaybackRate, OutputStreamTest>;
+TEST_P(PlaybackRateParametersHidlTest, PlaybackRateParametersTest) {
+ doc::test("Check that playback rate parameters can be set and retrieved");
+ testAccessors<OPTIONAL>(
+ &OutputStreamTest::getStream, "playback rate parameters",
+ Initial{PlaybackRate{1.0f, 1.0f, TimestretchMode::DEFAULT,
+ TimestretchFallbackMode::FAIL}},
+ {// Speed and pitch values in the range from 0.5f to 2.0f must be supported
+ // (see the definition of IStreamOut::setPlaybackRateParameters).
+ PlaybackRate{1.0f, 1.0f, TimestretchMode::DEFAULT, TimestretchFallbackMode::MUTE},
+ PlaybackRate{2.0f, 2.0f, TimestretchMode::DEFAULT, TimestretchFallbackMode::MUTE},
+ PlaybackRate{0.5f, 0.5f, TimestretchMode::DEFAULT, TimestretchFallbackMode::MUTE},
+ // Gross speed / pitch values must not be rejected if the fallback mode is "mute"
+ PlaybackRate{1000.0f, 1000.0f, TimestretchMode::DEFAULT,
+ TimestretchFallbackMode::MUTE},
+ // Default speed / pitch values must not be rejected in "fail" fallback mode
+ PlaybackRate{1.0f, 1.0f, TimestretchMode::DEFAULT, TimestretchFallbackMode::FAIL},
+ // Same for "voice" mode
+ PlaybackRate{1.0f, 1.0f, TimestretchMode::VOICE, TimestretchFallbackMode::MUTE},
+ PlaybackRate{2.0f, 2.0f, TimestretchMode::VOICE, TimestretchFallbackMode::MUTE},
+ PlaybackRate{0.5f, 0.5f, TimestretchMode::VOICE, TimestretchFallbackMode::MUTE},
+ PlaybackRate{1000.0f, 1000.0f, TimestretchMode::VOICE, TimestretchFallbackMode::MUTE},
+ PlaybackRate{1.0f, 1.0f, TimestretchMode::VOICE, TimestretchFallbackMode::FAIL}},
+ &IStreamOut::setPlaybackRateParameters, &IStreamOut::getPlaybackRateParameters,
+ {PlaybackRate{1000.0f, 1000.0f, TimestretchMode::DEFAULT,
+ TimestretchFallbackMode::FAIL},
+ PlaybackRate{1000.0f, 1000.0f, TimestretchMode::VOICE,
+ TimestretchFallbackMode::FAIL}});
+}
+
+INSTANTIATE_TEST_CASE_P(PlaybackRateParametersHidl, PlaybackRateParametersHidlTest,
+ ::testing::ValuesIn(getOutputDeviceConfigParameters()),
+ &DeviceConfigParameterToString);