Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(213)

Side by Side Diff: media/base/multi_channel_resampler.cc

Issue 14189035: Reduce jitter from uneven SincResampler buffer size requests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments. Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/base/multi_channel_resampler.h ('k') | media/base/multi_channel_resampler_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/base/multi_channel_resampler.h" 5 #include "media/base/multi_channel_resampler.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "media/base/audio_bus.h" 10 #include "media/base/audio_bus.h"
11 11
12 namespace media { 12 namespace media {
13 13
14 MultiChannelResampler::MultiChannelResampler(int channels, 14 MultiChannelResampler::MultiChannelResampler(int channels,
15 double io_sample_rate_ratio, 15 double io_sample_rate_ratio,
16 size_t request_size,
16 const ReadCB& read_cb) 17 const ReadCB& read_cb)
17 : last_frame_count_(0), 18 : last_frame_count_(0),
18 read_cb_(read_cb), 19 read_cb_(read_cb),
19 output_frames_ready_(0) { 20 output_frames_ready_(0) {
20 // Allocate each channel's resampler. 21 // Allocate each channel's resampler.
21 resamplers_.reserve(channels); 22 resamplers_.reserve(channels);
22 for (int i = 0; i < channels; ++i) { 23 for (int i = 0; i < channels; ++i) {
23 resamplers_.push_back(new SincResampler(io_sample_rate_ratio, base::Bind( 24 resamplers_.push_back(new SincResampler(
24 &MultiChannelResampler::ProvideInput, base::Unretained(this), i))); 25 io_sample_rate_ratio, request_size, base::Bind(
26 &MultiChannelResampler::ProvideInput, base::Unretained(this), i)));
25 } 27 }
26 } 28 }
27 29
28 MultiChannelResampler::~MultiChannelResampler() {} 30 MultiChannelResampler::~MultiChannelResampler() {}
29 31
30 void MultiChannelResampler::Resample(AudioBus* audio_bus, int frames) { 32 void MultiChannelResampler::Resample(int frames, AudioBus* audio_bus) {
31 DCHECK_EQ(static_cast<size_t>(audio_bus->channels()), resamplers_.size()); 33 DCHECK_EQ(static_cast<size_t>(audio_bus->channels()), resamplers_.size());
32 34
35 // Optimize the single channel case to avoid the chunking process below.
36 if (audio_bus->channels() == 1) {
37 resamplers_[0]->Resample(frames, audio_bus->channel(0));
38 return;
39 }
40
33 // We need to ensure that SincResampler only calls ProvideInput once for each 41 // We need to ensure that SincResampler only calls ProvideInput once for each
34 // channel. To ensure this, we chunk the number of requested frames into 42 // channel. To ensure this, we chunk the number of requested frames into
35 // SincResampler::ChunkSize() sized chunks. SincResampler guarantees it will 43 // SincResampler::ChunkSize() sized chunks. SincResampler guarantees it will
36 // only call ProvideInput() once when we resample this way. 44 // only call ProvideInput() once when we resample this way.
37 output_frames_ready_ = 0; 45 output_frames_ready_ = 0;
38 int chunk_size = resamplers_[0]->ChunkSize();
39 while (output_frames_ready_ < frames) { 46 while (output_frames_ready_ < frames) {
47 int chunk_size = resamplers_[0]->ChunkSize();
40 int frames_this_time = std::min(frames - output_frames_ready_, chunk_size); 48 int frames_this_time = std::min(frames - output_frames_ready_, chunk_size);
41 49
42 // Resample each channel. 50 // Resample each channel.
43 for (size_t i = 0; i < resamplers_.size(); ++i) { 51 for (size_t i = 0; i < resamplers_.size(); ++i) {
44 DCHECK_EQ(chunk_size, resamplers_[i]->ChunkSize()); 52 DCHECK_EQ(chunk_size, resamplers_[i]->ChunkSize());
45 53
46 // Depending on the sample-rate scale factor, and the internal buffering 54 // Depending on the sample-rate scale factor, and the internal buffering
47 // used in a SincResampler kernel, this call to Resample() will only 55 // used in a SincResampler kernel, this call to Resample() will only
48 // sometimes call ProvideInput(). However, if it calls ProvideInput() for 56 // sometimes call ProvideInput(). However, if it calls ProvideInput() for
49 // the first channel, then it will call it for the remaining channels, 57 // the first channel, then it will call it for the remaining channels,
50 // since they all buffer in the same way and are processing the same 58 // since they all buffer in the same way and are processing the same
51 // number of frames. 59 // number of frames.
52 resamplers_[i]->Resample( 60 resamplers_[i]->Resample(
53 audio_bus->channel(i) + output_frames_ready_, frames_this_time); 61 frames_this_time, audio_bus->channel(i) + output_frames_ready_);
54 } 62 }
55 63
56 output_frames_ready_ += frames_this_time; 64 output_frames_ready_ += frames_this_time;
57 } 65 }
58 } 66 }
59 67
60 void MultiChannelResampler::ProvideInput(int channel, float* destination, 68 void MultiChannelResampler::ProvideInput(int channel,
61 int frames) { 69 int frames,
70 float* destination) {
62 // Get the data from the multi-channel provider when the first channel asks 71 // Get the data from the multi-channel provider when the first channel asks
63 // for it. For subsequent channels, we can just dish out the channel data 72 // for it. For subsequent channels, we can just dish out the channel data
64 // from that (stored in |resampler_audio_bus_|). 73 // from that (stored in |resampler_audio_bus_|).
65 if (channel == 0) { 74 if (channel == 0) {
66 // Allocate staging arrays on the first request and if the frame size or 75 // Allocate staging arrays on the first request and if the frame size or
67 // |destination| changes (should only happen once). 76 // |destination| changes (should only happen once).
68 if (!resampler_audio_bus_.get() || 77 if (!resampler_audio_bus_.get() ||
69 resampler_audio_bus_->frames() != frames || 78 resampler_audio_bus_->frames() != frames ||
70 wrapped_resampler_audio_bus_->channel(0) != destination) { 79 wrapped_resampler_audio_bus_->channel(0) != destination) {
71 resampler_audio_bus_ = AudioBus::Create(resamplers_.size(), frames); 80 resampler_audio_bus_ = AudioBus::Create(resamplers_.size(), frames);
(...skipping 28 matching lines...) Expand all
100 for (size_t i = 0; i < resamplers_.size(); ++i) 109 for (size_t i = 0; i < resamplers_.size(); ++i)
101 resamplers_[i]->Flush(); 110 resamplers_[i]->Flush();
102 } 111 }
103 112
104 void MultiChannelResampler::SetRatio(double io_sample_rate_ratio) { 113 void MultiChannelResampler::SetRatio(double io_sample_rate_ratio) {
105 for (size_t i = 0; i < resamplers_.size(); ++i) 114 for (size_t i = 0; i < resamplers_.size(); ++i)
106 resamplers_[i]->SetRatio(io_sample_rate_ratio); 115 resamplers_[i]->SetRatio(io_sample_rate_ratio);
107 } 116 }
108 117
109 } // namespace media 118 } // namespace media
OLDNEW
« no previous file with comments | « media/base/multi_channel_resampler.h ('k') | media/base/multi_channel_resampler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698