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

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

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

Powered by Google App Engine
This is Rietveld 408576698