OLD | NEW |
---|---|
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 // AudioConverter implementation. Uses MultiChannelSincResampler for resampling | 5 // AudioConverter implementation. Uses MultiChannelSincResampler for resampling |
6 // audio, ChannelMixer for channel mixing, and AudioPullFifo for buffering. | 6 // audio, ChannelMixer for channel mixing, and AudioPullFifo for buffering. |
7 // | 7 // |
8 // Delay estimates are provided to InputCallbacks based on the frame delay | 8 // Delay estimates are provided to InputCallbacks based on the frame delay |
9 // information reported via the resampler and FIFO units. | 9 // information reported via the resampler and FIFO units. |
10 | 10 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
49 // since we'll mix into the AudioBus from the output stream. | 49 // since we'll mix into the AudioBus from the output stream. |
50 unmixed_audio_ = AudioBus::Create( | 50 unmixed_audio_ = AudioBus::Create( |
51 input_params.channels(), output_params.frames_per_buffer()); | 51 input_params.channels(), output_params.frames_per_buffer()); |
52 } | 52 } |
53 } | 53 } |
54 | 54 |
55 // Only resample if necessary since it's expensive. | 55 // Only resample if necessary since it's expensive. |
56 if (input_params.sample_rate() != output_params.sample_rate()) { | 56 if (input_params.sample_rate() != output_params.sample_rate()) { |
57 DVLOG(1) << "Resampling from " << input_params.sample_rate() << " to " | 57 DVLOG(1) << "Resampling from " << input_params.sample_rate() << " to " |
58 << output_params.sample_rate(); | 58 << output_params.sample_rate(); |
59 double io_sample_rate_ratio = input_params.sample_rate() / | 59 const double io_sample_rate_ratio = input_params.sample_rate() / |
60 static_cast<double>(output_params.sample_rate()); | 60 static_cast<double>(output_params.sample_rate()); |
61 const int request_size = disable_fifo ? SincResampler::kDefaultRequestSize : | |
62 input_params.frames_per_buffer(); | |
61 resampler_.reset(new MultiChannelResampler( | 63 resampler_.reset(new MultiChannelResampler( |
62 downmix_early_ ? output_params.channels() : | 64 downmix_early_ ? output_params.channels() : |
63 input_params.channels(), | 65 input_params.channels(), |
64 io_sample_rate_ratio, base::Bind( | 66 io_sample_rate_ratio, request_size, base::Bind( |
65 &AudioConverter::ProvideInput, base::Unretained(this)))); | 67 &AudioConverter::ProvideInput, base::Unretained(this)))); |
66 } | 68 } |
67 | 69 |
68 input_frame_duration_ = base::TimeDelta::FromMicroseconds( | 70 input_frame_duration_ = base::TimeDelta::FromMicroseconds( |
69 base::Time::kMicrosecondsPerSecond / | 71 base::Time::kMicrosecondsPerSecond / |
70 static_cast<double>(input_params.sample_rate())); | 72 static_cast<double>(input_params.sample_rate())); |
71 output_frame_duration_ = base::TimeDelta::FromMicroseconds( | 73 output_frame_duration_ = base::TimeDelta::FromMicroseconds( |
72 base::Time::kMicrosecondsPerSecond / | 74 base::Time::kMicrosecondsPerSecond / |
73 static_cast<double>(output_params.sample_rate())); | 75 static_cast<double>(output_params.sample_rate())); |
74 | 76 |
75 if (disable_fifo) | 77 // The resampler can be configured to work with a specific buffer size, so a |
Chris Rogers
2013/05/07 22:57:53
nit: "specific buffer size" -> "specific request b
DaleCurtis
2013/05/07 23:49:41
Changed to request size for consistency with SincR
| |
78 // FIFO is not necessary when resampling. | |
79 if (disable_fifo || resampler_) | |
76 return; | 80 return; |
77 | 81 |
78 // Since the resampler / output device may want a different buffer size than | 82 // Since the output device may want a different buffer size than the caller |
79 // the caller asked for, we need to use a FIFO to ensure that both sides | 83 // asked for, we need to use a FIFO to ensure that both sides read in chunk |
80 // read in chunk sizes they're configured for. | 84 // sizes they're configured for. |
81 if (resampler_.get() || | 85 if (input_params.frames_per_buffer() != output_params.frames_per_buffer()) { |
82 input_params.frames_per_buffer() != output_params.frames_per_buffer()) { | |
83 DVLOG(1) << "Rebuffering from " << input_params.frames_per_buffer() | 86 DVLOG(1) << "Rebuffering from " << input_params.frames_per_buffer() |
84 << " to " << output_params.frames_per_buffer(); | 87 << " to " << output_params.frames_per_buffer(); |
85 audio_fifo_.reset(new AudioPullFifo( | 88 audio_fifo_.reset(new AudioPullFifo( |
86 downmix_early_ ? output_params.channels() : | 89 downmix_early_ ? output_params.channels() : |
87 input_params.channels(), | 90 input_params.channels(), |
88 input_params.frames_per_buffer(), base::Bind( | 91 input_params.frames_per_buffer(), base::Bind( |
89 &AudioConverter::SourceCallback, | 92 &AudioConverter::SourceCallback, |
90 base::Unretained(this)))); | 93 base::Unretained(this)))); |
91 } | 94 } |
92 } | 95 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
134 AudioBus* temp_dest = needs_mixing ? unmixed_audio_.get() : dest; | 137 AudioBus* temp_dest = needs_mixing ? unmixed_audio_.get() : dest; |
135 DCHECK(temp_dest); | 138 DCHECK(temp_dest); |
136 | 139 |
137 // Figure out which method to call based on whether we're resampling and | 140 // Figure out which method to call based on whether we're resampling and |
138 // rebuffering, just resampling, or just mixing. We want to avoid any extra | 141 // rebuffering, just resampling, or just mixing. We want to avoid any extra |
139 // steps when possible since we may be converting audio data in real time. | 142 // steps when possible since we may be converting audio data in real time. |
140 if (!resampler_ && !audio_fifo_) { | 143 if (!resampler_ && !audio_fifo_) { |
141 SourceCallback(0, temp_dest); | 144 SourceCallback(0, temp_dest); |
142 } else { | 145 } else { |
143 if (resampler_) | 146 if (resampler_) |
144 resampler_->Resample(temp_dest, temp_dest->frames()); | 147 resampler_->Resample(temp_dest->frames(), temp_dest); |
145 else | 148 else |
146 ProvideInput(0, temp_dest); | 149 ProvideInput(0, temp_dest); |
147 } | 150 } |
148 | 151 |
149 // Finally upmix the channels if we didn't do so earlier. | 152 // Finally upmix the channels if we didn't do so earlier. |
150 if (needs_mixing) { | 153 if (needs_mixing) { |
151 DCHECK_EQ(temp_dest->frames(), dest->frames()); | 154 DCHECK_EQ(temp_dest->frames(), dest->frames()); |
152 channel_mixer_->Transform(temp_dest, dest); | 155 channel_mixer_->Transform(temp_dest, dest); |
153 } | 156 } |
154 } | 157 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
235 | 238 |
236 void AudioConverter::ProvideInput(int resampler_frame_delay, AudioBus* dest) { | 239 void AudioConverter::ProvideInput(int resampler_frame_delay, AudioBus* dest) { |
237 resampler_frame_delay_ = resampler_frame_delay; | 240 resampler_frame_delay_ = resampler_frame_delay; |
238 if (audio_fifo_) | 241 if (audio_fifo_) |
239 audio_fifo_->Consume(dest, dest->frames()); | 242 audio_fifo_->Consume(dest, dest->frames()); |
240 else | 243 else |
241 SourceCallback(0, dest); | 244 SourceCallback(0, dest); |
242 } | 245 } |
243 | 246 |
244 } // namespace media | 247 } // namespace media |
OLD | NEW |