Index: trunk/src/media/filters/audio_renderer_algorithm.cc |
=================================================================== |
--- trunk/src/media/filters/audio_renderer_algorithm.cc (revision 274695) |
+++ trunk/src/media/filters/audio_renderer_algorithm.cc (working copy) |
@@ -46,6 +46,12 @@ |
// |search_block_index_| = |search_block_center_offset_| - |
// |search_block_center_offset_|. |
+// Max/min supported playback rates for fast/slow audio. Audio outside of these |
+// ranges are muted. |
+// Audio at these speeds would sound better under a frequency domain algorithm. |
+static const float kMinPlaybackRate = 0.5f; |
+static const float kMaxPlaybackRate = 4.0f; |
+ |
// Overlap-and-add window size in milliseconds. |
static const int kOlaWindowSizeMs = 20; |
@@ -70,6 +76,8 @@ |
: channels_(0), |
samples_per_second_(0), |
playback_rate_(0), |
+ muted_(false), |
+ muted_partial_frame_(0), |
capacity_(kStartingBufferSizeInFrames), |
output_time_(0.0), |
search_block_center_offset_(0), |
@@ -143,6 +151,31 @@ |
DCHECK_EQ(channels_, dest->channels()); |
+ // Optimize the |muted_| case to issue a single clear instead of performing |
+ // the full crossfade and clearing each crossfaded frame. |
+ if (muted_) { |
+ int frames_to_render = |
+ std::min(static_cast<int>(audio_buffer_.frames() / playback_rate_), |
+ requested_frames); |
+ |
+ // Compute accurate number of frames to actually skip in the source data. |
+ // Includes the leftover partial frame from last request. However, we can |
+ // only skip over complete frames, so a partial frame may remain for next |
+ // time. |
+ muted_partial_frame_ += frames_to_render * playback_rate_; |
+ int seek_frames = static_cast<int>(muted_partial_frame_); |
+ dest->ZeroFrames(frames_to_render); |
+ audio_buffer_.SeekFrames(seek_frames); |
+ |
+ // Determine the partial frame that remains to be skipped for next call. If |
+ // the user switches back to playing, it may be off time by this partial |
+ // frame, which would be undetectable. If they subsequently switch to |
+ // another playback rate that mutes, the code will attempt to line up the |
+ // frames again. |
+ muted_partial_frame_ -= seek_frames; |
+ return frames_to_render; |
+ } |
+ |
int slower_step = ceil(ola_window_size_ * playback_rate_); |
int faster_step = ceil(ola_window_size_ / playback_rate_); |
@@ -167,6 +200,8 @@ |
void AudioRendererAlgorithm::SetPlaybackRate(float new_rate) { |
DCHECK_GE(new_rate, 0); |
playback_rate_ = new_rate; |
+ muted_ = |
+ playback_rate_ < kMinPlaybackRate || playback_rate_ > kMaxPlaybackRate; |
} |
void AudioRendererAlgorithm::FlushBuffers() { |