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

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

Issue 11410012: Collapse AudioRendererMixer and OnMoreDataResampler into AudioTransform. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rename. Comments. Created 8 years, 1 month 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 const ReadCB& read_cb) 16 const ReadCB& read_cb)
17 : last_frame_count_(0), 17 : last_frame_count_(0),
18 read_cb_(read_cb) { 18 read_cb_(read_cb),
19 output_frames_ready_(0) {
19 // Allocate each channel's resampler. 20 // Allocate each channel's resampler.
20 resamplers_.reserve(channels); 21 resamplers_.reserve(channels);
21 for (int i = 0; i < channels; ++i) { 22 for (int i = 0; i < channels; ++i) {
22 resamplers_.push_back(new SincResampler(io_sample_rate_ratio, base::Bind( 23 resamplers_.push_back(new SincResampler(io_sample_rate_ratio, base::Bind(
23 &MultiChannelResampler::ProvideInput, base::Unretained(this), i))); 24 &MultiChannelResampler::ProvideInput, base::Unretained(this), i)));
24 } 25 }
25 } 26 }
26 27
27 MultiChannelResampler::~MultiChannelResampler() {} 28 MultiChannelResampler::~MultiChannelResampler() {}
28 29
29 void MultiChannelResampler::Resample(AudioBus* audio_bus, int frames) { 30 void MultiChannelResampler::Resample(AudioBus* audio_bus, int frames) {
30 DCHECK_EQ(static_cast<size_t>(audio_bus->channels()), resamplers_.size()); 31 DCHECK_EQ(static_cast<size_t>(audio_bus->channels()), resamplers_.size());
31 32
32 // We need to ensure that SincResampler only calls ProvideInput once for each 33 // We need to ensure that SincResampler only calls ProvideInput once for each
33 // channel. To ensure this, we chunk the number of requested frames into 34 // channel. To ensure this, we chunk the number of requested frames into
34 // SincResampler::ChunkSize() sized chunks. SincResampler guarantees it will 35 // SincResampler::ChunkSize() sized chunks. SincResampler guarantees it will
35 // only call ProvideInput() once when we resample this way. 36 // only call ProvideInput() once when we resample this way.
36 int frames_done = 0; 37 output_frames_ready_ = 0;
37 int chunk_size = resamplers_[0]->ChunkSize(); 38 int chunk_size = resamplers_[0]->ChunkSize();
38 while (frames_done < frames) { 39 while (output_frames_ready_ < frames) {
39 int frames_this_time = std::min(frames - frames_done, chunk_size); 40 int frames_this_time = std::min(frames - output_frames_ready_, chunk_size);
40 41
41 // Resample each channel. 42 // Resample each channel.
42 for (size_t i = 0; i < resamplers_.size(); ++i) { 43 for (size_t i = 0; i < resamplers_.size(); ++i) {
43 DCHECK_EQ(chunk_size, resamplers_[i]->ChunkSize()); 44 DCHECK_EQ(chunk_size, resamplers_[i]->ChunkSize());
44 45
45 // Depending on the sample-rate scale factor, and the internal buffering 46 // Depending on the sample-rate scale factor, and the internal buffering
46 // used in a SincResampler kernel, this call to Resample() will only 47 // used in a SincResampler kernel, this call to Resample() will only
47 // sometimes call ProvideInput(). However, if it calls ProvideInput() for 48 // sometimes call ProvideInput(). However, if it calls ProvideInput() for
48 // the first channel, then it will call it for the remaining channels, 49 // the first channel, then it will call it for the remaining channels,
49 // since they all buffer in the same way and are processing the same 50 // since they all buffer in the same way and are processing the same
50 // number of frames. 51 // number of frames.
51 resamplers_[i]->Resample( 52 resamplers_[i]->Resample(
52 audio_bus->channel(i) + frames_done, frames_this_time); 53 audio_bus->channel(i) + output_frames_ready_, frames_this_time);
53 } 54 }
54 55
55 frames_done += frames_this_time; 56 output_frames_ready_ += frames_this_time;
56 } 57 }
57 } 58 }
58 59
59 void MultiChannelResampler::ProvideInput(int channel, float* destination, 60 void MultiChannelResampler::ProvideInput(int channel, float* destination,
60 int frames) { 61 int frames) {
61 // Get the data from the multi-channel provider when the first channel asks 62 // Get the data from the multi-channel provider when the first channel asks
62 // for it. For subsequent channels, we can just dish out the channel data 63 // for it. For subsequent channels, we can just dish out the channel data
63 // from that (stored in |resampler_audio_bus_|). 64 // from that (stored in |resampler_audio_bus_|).
64 if (channel == 0) { 65 if (channel == 0) {
65 // Allocate staging arrays on the first request and if the frame size or 66 // Allocate staging arrays on the first request and if the frame size or
66 // |destination| changes (should only happen once). 67 // |destination| changes (should only happen once).
67 if (!resampler_audio_bus_.get() || 68 if (!resampler_audio_bus_.get() ||
68 resampler_audio_bus_->frames() != frames || 69 resampler_audio_bus_->frames() != frames ||
69 wrapped_resampler_audio_bus_->channel(0) != destination) { 70 wrapped_resampler_audio_bus_->channel(0) != destination) {
70 resampler_audio_bus_ = AudioBus::Create(resamplers_.size(), frames); 71 resampler_audio_bus_ = AudioBus::Create(resamplers_.size(), frames);
71 72
72 // Create a channel vector based on |resampler_audio_bus_| but using 73 // Create a channel vector based on |resampler_audio_bus_| but using
73 // |destination| directly for the first channel and then wrap it in a new 74 // |destination| directly for the first channel and then wrap it in a new
74 // AudioBus so we can avoid an extra memcpy later. 75 // AudioBus so we can avoid an extra memcpy later.
75 resampler_audio_data_.clear(); 76 resampler_audio_data_.clear();
76 resampler_audio_data_.reserve(resampler_audio_bus_->channels()); 77 resampler_audio_data_.reserve(resampler_audio_bus_->channels());
77 resampler_audio_data_.push_back(destination); 78 resampler_audio_data_.push_back(destination);
78 for (int i = 1; i < resampler_audio_bus_->channels(); ++i) 79 for (int i = 1; i < resampler_audio_bus_->channels(); ++i)
79 resampler_audio_data_.push_back(resampler_audio_bus_->channel(i)); 80 resampler_audio_data_.push_back(resampler_audio_bus_->channel(i));
80 wrapped_resampler_audio_bus_ = AudioBus::WrapVector( 81 wrapped_resampler_audio_bus_ = AudioBus::WrapVector(
81 frames, resampler_audio_data_); 82 frames, resampler_audio_data_);
82 } 83 }
83 84
84 last_frame_count_ = frames; 85 last_frame_count_ = frames;
85 read_cb_.Run(wrapped_resampler_audio_bus_.get()); 86 read_cb_.Run(output_frames_ready_, wrapped_resampler_audio_bus_.get());
86 } else { 87 } else {
87 // All channels must ask for the same amount. This should always be the 88 // All channels must ask for the same amount. This should always be the
88 // case, but let's just make sure. 89 // case, but let's just make sure.
89 DCHECK_EQ(frames, last_frame_count_); 90 DCHECK_EQ(frames, last_frame_count_);
90 91
91 // Copy the channel data from what we received from |read_cb_|. 92 // Copy the channel data from what we received from |read_cb_|.
92 memcpy(destination, resampler_audio_bus_->channel(channel), 93 memcpy(destination, resampler_audio_bus_->channel(channel),
93 sizeof(*resampler_audio_bus_->channel(channel)) * frames); 94 sizeof(*resampler_audio_bus_->channel(channel)) * frames);
94 } 95 }
95 } 96 }
96 97
97 void MultiChannelResampler::Flush() { 98 void MultiChannelResampler::Flush() {
98 last_frame_count_ = 0; 99 last_frame_count_ = 0;
99 for (size_t i = 0; i < resamplers_.size(); ++i) 100 for (size_t i = 0; i < resamplers_.size(); ++i)
100 resamplers_[i]->Flush(); 101 resamplers_[i]->Flush();
101 } 102 }
102 103
103 } // namespace media 104 } // 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