| 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 request size, so a |
| 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 |