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

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

Issue 10698066: Switch to pcm_low_latency and enable resampling. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: First Look! Created 8 years, 5 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/audio_renderer_mixer.h ('k') | media/base/audio_renderer_mixer_input.h » ('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/audio_renderer_mixer.h" 5 #include "media/base/audio_renderer_mixer.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "media/audio/audio_util.h"
8 9
9 namespace media { 10 namespace media {
10 11
11 AudioRendererMixer::AudioRendererMixer( 12 AudioRendererMixer::AudioRendererMixer(
12 const AudioParameters& params, const scoped_refptr<AudioRendererSink>& sink) 13 const AudioParameters& params, const scoped_refptr<AudioRendererSink>& sink)
13 : audio_parameters_(params), 14 : audio_sink_(sink),
14 audio_sink_(sink) { 15 current_audio_delay_milliseconds_(0) {
15 // TODO(dalecurtis): Once we have resampling we'll need to pass on a different 16 // Create output parameters for passing on to the output sink.
16 // set of AudioParameters than the ones we're given. 17 // TODO(dalecurtis): There's a lot of buffer trickery to figure out here...
17 audio_sink_->Initialize(audio_parameters_, this); 18 // TODO(dalecurtis): What about the values set in AudioRendererImpl?
19 // TODO(dalecurtis): All this buffer logic should be shared between WebRTC,
20 // Pepper, etc.
21 int output_sample_rate = GetAudioHardwareSampleRate();
22 output_parameters_ = AudioParameters(
23 AudioParameters::AUDIO_PCM_LOW_LATENCY, params.channel_layout(),
24 output_sample_rate, 16, output_sample_rate / 100);
Chris Rogers 2012/07/02 22:53:50 Instead of output_sample_rate / 100, better to use
DaleCurtis 2012/07/12 00:40:44 Done.
25
26 // Only resample if necessary since it's expensive.
27 if (params.sample_rate() != output_sample_rate)
Chris Rogers 2012/07/02 22:53:50 Maybe some basic sanity checking on params.sample_
DaleCurtis 2012/07/12 00:40:44 Done.
28 resampler_.reset(new MultiChannelResampler(
29 this, params.sample_rate() / static_cast<float>(output_sample_rate),
30 output_parameters_.channels()));
31
32 // Preallocate staging area for collecting each mixer input's audio data.
33 // TODO(dalecurtis): If we switch to AVX/SSE optimization, we'll need to
34 // allocate these on 32-byte boundaries and ensure they're sized % 32 bytes.
35 mixer_input_audio_data_.reserve(output_parameters_.channels());
36 for (int i = 0; i < output_parameters_.channels(); ++i)
37 mixer_input_audio_data_.push_back(
38 new float[output_parameters_.frames_per_buffer()]);
39
40 audio_sink_->Initialize(output_parameters_, this);
18 audio_sink_->Start(); 41 audio_sink_->Start();
19 } 42 }
20 43
21 AudioRendererMixer::~AudioRendererMixer() { 44 AudioRendererMixer::~AudioRendererMixer() {
22 // AudioRendererSinks must be stopped before being destructed. 45 // AudioRendererSinks must be stopped before being destructed.
23 audio_sink_->Stop(); 46 audio_sink_->Stop();
24 47
48 // Clean up |mixer_input_audio_data_|.
49 for (size_t i = 0; i < mixer_input_audio_data_.size(); ++i)
50 delete [] mixer_input_audio_data_[i];
51 mixer_input_audio_data_.clear();
52
25 // Ensures that all mixer inputs have stopped themselves prior to destruction 53 // Ensures that all mixer inputs have stopped themselves prior to destruction
26 // and have called RemoveMixerInput(). 54 // and have called RemoveMixerInput().
27 DCHECK_EQ(mixer_inputs_.size(), 0U); 55 DCHECK_EQ(mixer_inputs_.size(), 0U);
28 } 56 }
29 57
30 void AudioRendererMixer::AddMixerInput( 58 void AudioRendererMixer::AddMixerInput(
31 const scoped_refptr<AudioRendererMixerInput>& input) { 59 const scoped_refptr<AudioRendererMixerInput>& input) {
32 base::AutoLock auto_lock(mixer_inputs_lock_); 60 base::AutoLock auto_lock(mixer_inputs_lock_);
33 mixer_inputs_.insert(input); 61 mixer_inputs_.insert(input);
34 } 62 }
35 63
36 void AudioRendererMixer::RemoveMixerInput( 64 void AudioRendererMixer::RemoveMixerInput(
37 const scoped_refptr<AudioRendererMixerInput>& input) { 65 const scoped_refptr<AudioRendererMixerInput>& input) {
38 base::AutoLock auto_lock(mixer_inputs_lock_); 66 base::AutoLock auto_lock(mixer_inputs_lock_);
39 mixer_inputs_.erase(input); 67 mixer_inputs_.erase(input);
40 } 68 }
41 69
42 int AudioRendererMixer::Render(const std::vector<float*>& audio_data, 70 int AudioRendererMixer::Render(const std::vector<float*>& audio_data,
43 int number_of_frames, 71 int number_of_frames,
44 int audio_delay_milliseconds) { 72 int audio_delay_milliseconds) {
73 current_audio_delay_milliseconds_ = audio_delay_milliseconds;
74
75 if (resampler_ != NULL)
76 resampler_->Resample(audio_data, number_of_frames);
77 else
78 ProvideInput(audio_data, number_of_frames);
79
80 // Always return the full number of frames requested, we padded with silence
81 // if we couldn't get enough data.
Chris Rogers 2012/07/02 22:53:50 nit: fix up grammar here
DaleCurtis 2012/07/12 00:40:44 Done.
82 return number_of_frames;
83 }
84
85 void AudioRendererMixer::ProvideInput(const std::vector<float*>& audio_data,
86 int number_of_frames) {
45 base::AutoLock auto_lock(mixer_inputs_lock_); 87 base::AutoLock auto_lock(mixer_inputs_lock_);
46 88
89 // Sanity check our inputs.
90 DCHECK_LE(number_of_frames, output_parameters_.frames_per_buffer());
91 DCHECK_EQ(static_cast<int>(audio_data.size()), output_parameters_.channels());
92
47 // Zero |audio_data| so we're mixing into a clean buffer and return silence if 93 // Zero |audio_data| so we're mixing into a clean buffer and return silence if
48 // we couldn't get enough data from our inputs. 94 // we couldn't get enough data from our inputs.
49 for (int i = 0; i < audio_parameters_.channels(); ++i) 95 for (size_t i = 0; i < audio_data.size(); ++i)
50 memset(audio_data[i], 0, number_of_frames * sizeof(*audio_data[i])); 96 memset(audio_data[i], 0, number_of_frames * sizeof(*audio_data[i]));
51 97
52 // Have each mixer render its data into an output buffer then mix the result. 98 // Have each mixer render its data into an output buffer then mix the result.
53 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin(); 99 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin();
54 it != mixer_inputs_.end(); ++it) { 100 it != mixer_inputs_.end(); ++it) {
55 const scoped_refptr<AudioRendererMixerInput>& input = *it; 101 const scoped_refptr<AudioRendererMixerInput>& input = *it;
56 102
57 double volume; 103 double volume;
58 input->GetVolume(&volume); 104 input->GetVolume(&volume);
59 105
60 // Nothing to do if the input isn't playing or the volume is zero. 106 // Nothing to do if the input isn't playing.
61 if (!input->playing() || volume == 0.0f) 107 if (!input->playing())
62 continue; 108 continue;
63 109
64 const std::vector<float*>& mixer_input_audio_data = input->audio_data();
65
66 int frames_filled = input->callback()->Render( 110 int frames_filled = input->callback()->Render(
Chris Rogers 2012/07/02 22:53:50 small nit: this isn't new to this patch, but it st
67 mixer_input_audio_data, number_of_frames, audio_delay_milliseconds); 111 mixer_input_audio_data_, number_of_frames,
112 current_audio_delay_milliseconds_);
68 if (frames_filled == 0) 113 if (frames_filled == 0)
69 continue; 114 continue;
70 115
71 // TODO(dalecurtis): Resample audio data.
72
73 // Volume adjust and mix each mixer input into |audio_data| after rendering. 116 // Volume adjust and mix each mixer input into |audio_data| after rendering.
74 // TODO(dalecurtis): Optimize with NEON/SSE/AVX vector_fmac from FFmpeg. 117 // TODO(dalecurtis): Optimize with NEON/SSE/AVX vector_fmac from FFmpeg.
75 for (int j = 0; j < audio_parameters_.channels(); ++j) { 118 for (size_t j = 0; j < audio_data.size(); ++j) {
76 float* dest = audio_data[j]; 119 float* dest = audio_data[j];
77 float* source = mixer_input_audio_data[j]; 120 float* source = mixer_input_audio_data_[j];
78 for (int k = 0; k < frames_filled; ++k) 121 for (int k = 0; k < frames_filled; ++k)
79 dest[k] += source[k] * static_cast<float>(volume); 122 dest[k] += source[k] * static_cast<float>(volume);
80 } 123 }
81 124
82 // No need to clamp values as InterleaveFloatToInt() will take care of this 125 // No need to clamp values as InterleaveFloatToInt() will take care of this
83 // for us later when data is transferred to the browser process. 126 // for us later when data is transferred to the browser process.
127 // TODO(dalecurtis): Does the resampler need values betwen [-1, 1] ?
Chris Rogers 2012/07/02 22:53:50 The resampler will be fine. I'd just entirely rem
84 } 128 }
85
86 // Always return the full number of frames requested, padded with silence if
87 // we couldn't get enough data.
88 return number_of_frames;
89 } 129 }
90 130
91 void AudioRendererMixer::OnRenderError() { 131 void AudioRendererMixer::OnRenderError() {
92 base::AutoLock auto_lock(mixer_inputs_lock_); 132 base::AutoLock auto_lock(mixer_inputs_lock_);
93 133
94 // Call each mixer input and signal an error. 134 // Call each mixer input and signal an error.
95 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin(); 135 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin();
96 it != mixer_inputs_.end(); ++it) { 136 it != mixer_inputs_.end(); ++it) {
97 (*it)->callback()->OnRenderError(); 137 (*it)->callback()->OnRenderError();
98 } 138 }
99 } 139 }
100 140
101 } // namespace media 141 } // namespace media
OLDNEW
« no previous file with comments | « media/base/audio_renderer_mixer.h ('k') | media/base/audio_renderer_mixer_input.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698