Commit 6570ef0e by aquilescanta Committed by Andrew Lewis

Add support for AudioTrack pitch/speed alteration on API 23.

Issue #26
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=108958826
parent 33506ada
...@@ -24,6 +24,7 @@ import com.google.android.exoplayer.util.MimeTypes; ...@@ -24,6 +24,7 @@ import com.google.android.exoplayer.util.MimeTypes;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.PlaybackParams;
import android.media.audiofx.Virtualizer; import android.media.audiofx.Virtualizer;
import android.os.Handler; import android.os.Handler;
import android.os.SystemClock; import android.os.SystemClock;
...@@ -77,6 +78,14 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem ...@@ -77,6 +78,14 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem
public static final int MSG_SET_VOLUME = 1; public static final int MSG_SET_VOLUME = 1;
/** /**
* The type of a message that can be passed to an instance of this class via
* {@link ExoPlayer#sendMessage} or {@link ExoPlayer#blockingSendMessage}. The message object
* should be a {@link android.media.PlaybackParams}. This will be used to configure the
* underlying {@link android.media.AudioTrack}.
*/
public static final int MSG_SET_PLAYBACK_PARAMS = 2;
/**
* The name for the raw (passthrough) decoder OMX component. * The name for the raw (passthrough) decoder OMX component.
*/ */
private static final String RAW_DECODER_NAME = "OMX.google.raw.decoder"; private static final String RAW_DECODER_NAME = "OMX.google.raw.decoder";
...@@ -401,10 +410,16 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem ...@@ -401,10 +410,16 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem
@Override @Override
public void handleMessage(int messageType, Object message) throws ExoPlaybackException { public void handleMessage(int messageType, Object message) throws ExoPlaybackException {
if (messageType == MSG_SET_VOLUME) { switch (messageType) {
audioTrack.setVolume((Float) message); case MSG_SET_VOLUME:
} else { audioTrack.setVolume((Float) message);
super.handleMessage(messageType, message); break;
case MSG_SET_PLAYBACK_PARAMS:
audioTrack.setPlaybackParams((PlaybackParams) message);
break;
default:
super.handleMessage(messageType, message);
break;
} }
} }
......
...@@ -26,6 +26,7 @@ import android.media.AudioFormat; ...@@ -26,6 +26,7 @@ import android.media.AudioFormat;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.AudioTimestamp; import android.media.AudioTimestamp;
import android.media.MediaFormat; import android.media.MediaFormat;
import android.media.PlaybackParams;
import android.os.ConditionVariable; import android.os.ConditionVariable;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.Log; import android.util.Log;
...@@ -248,7 +249,9 @@ public final class AudioTrack { ...@@ -248,7 +249,9 @@ public final class AudioTrack {
// There's no guarantee this method exists. Do nothing. // There's no guarantee this method exists. Do nothing.
} }
} }
if (Util.SDK_INT >= 19) { if (Util.SDK_INT >= 23) {
audioTrackUtil = new AudioTrackUtilV23();
} else if (Util.SDK_INT >= 19) {
audioTrackUtil = new AudioTrackUtilV19(); audioTrackUtil = new AudioTrackUtilV19();
} else { } else {
audioTrackUtil = new AudioTrackUtil(); audioTrackUtil = new AudioTrackUtil();
...@@ -300,7 +303,10 @@ public final class AudioTrack { ...@@ -300,7 +303,10 @@ public final class AudioTrack {
if (audioTimestampSet) { if (audioTimestampSet) {
// How long ago in the past the audio timestamp is (negative if it's in the future). // How long ago in the past the audio timestamp is (negative if it's in the future).
long presentationDiff = systemClockUs - (audioTrackUtil.getTimestampNanoTime() / 1000); long presentationDiff = systemClockUs - (audioTrackUtil.getTimestampNanoTime() / 1000);
long framesDiff = durationUsToFrames(presentationDiff); // Fixes such difference if the playback speed is not real time speed.
long actualSpeedPresentationDiff = (long) (presentationDiff
* audioTrackUtil.getPlaybackSpeed());
long framesDiff = durationUsToFrames(actualSpeedPresentationDiff);
// The position of the frame that's currently being presented. // The position of the frame that's currently being presented.
long currentFramePosition = audioTrackUtil.getTimestampFramePosition() + framesDiff; long currentFramePosition = audioTrackUtil.getTimestampFramePosition() + framesDiff;
currentPositionUs = framesToDurationUs(currentFramePosition) + startMediaTimeUs; currentPositionUs = framesToDurationUs(currentFramePosition) + startMediaTimeUs;
...@@ -652,10 +658,21 @@ public final class AudioTrack { ...@@ -652,10 +658,21 @@ public final class AudioTrack {
public boolean hasPendingData() { public boolean hasPendingData() {
return isInitialized() return isInitialized()
&& (getSubmittedFrames() > audioTrackUtil.getPlaybackHeadPosition() && (getSubmittedFrames() > audioTrackUtil.getPlaybackHeadPosition()
|| overrideHasPendingData()); || overrideHasPendingData());
} }
/** /**
* Sets the playback parameters. Only available for SDK_INT >= 23
*
* @throws UnsupportedOperationException if the Playback Parameters are not supported. That is,
* SDK_INT < 23.
*/
public void setPlaybackParams(PlaybackParams playbackParams) {
audioTrackUtil.setPlaybackParameters(playbackParams);
}
/**
* Sets the playback volume. * Sets the playback volume.
*/ */
public void setVolume(float volume) { public void setVolume(float volume) {
...@@ -1100,6 +1117,27 @@ public final class AudioTrack { ...@@ -1100,6 +1117,27 @@ public final class AudioTrack {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
/**
* Sets the Playback Parameters to be used by the underlying {@link android.media.AudioTrack}.
*
* @param playbackParams to be used by the {@link android.media.AudioTrack}.
* @throws UnsupportedOperationException If Playback Parameters are not supported
* (i.e. SDK_INT < 23).
*/
public void setPlaybackParameters(PlaybackParams playbackParams) {
throw new UnsupportedOperationException();
}
/**
* Returns the configured playback speed according to the used Playback Parameters. If these are
* not supported, 1.0f(normal speed) is returned.
*
* @return The speed factor used by the underlying {@link android.media.AudioTrack}.
*/
public float getPlaybackSpeed() {
return 1.0f;
}
} }
@TargetApi(19) @TargetApi(19)
...@@ -1151,4 +1189,31 @@ public final class AudioTrack { ...@@ -1151,4 +1189,31 @@ public final class AudioTrack {
} }
@TargetApi(23)
private static class AudioTrackUtilV23 extends AudioTrackUtilV19 {
private PlaybackParams playbackParams;
@Override
public void reconfigure(android.media.AudioTrack audioTrack,
boolean needsPassthroughWorkaround) {
super.reconfigure(audioTrack, needsPassthroughWorkaround);
setPlaybackParameters(playbackParams);
}
public void setPlaybackParameters(PlaybackParams playbackParams) {
this.playbackParams = playbackParams;
if (audioTrack != null && playbackParams != null) {
audioTrack.setPlaybackParams(playbackParams);
}
}
public float getPlaybackSpeed() {
if (playbackParams != null) {
return playbackParams.getSpeed();
} else {
return 1.0f;
}
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment