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

Unified Diff: content/renderer/media/webrtc_audio_device_impl.cc

Issue 9702019: Adds Analog Gain Control (AGC) to the WebRTC client. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Improved volume updating on Mac Created 8 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: content/renderer/media/webrtc_audio_device_impl.cc
diff --git a/content/renderer/media/webrtc_audio_device_impl.cc b/content/renderer/media/webrtc_audio_device_impl.cc
index 1293674e14c2e0c2a4395694068430d71ab4d277..2928bc514ba806250c6a9427c7b0ea5ac1b8a97f 100644
--- a/content/renderer/media/webrtc_audio_device_impl.cc
+++ b/content/renderer/media/webrtc_audio_device_impl.cc
@@ -12,6 +12,7 @@
#include "media/audio/audio_util.h"
static const int64 kMillisecondsBetweenProcessCalls = 5000;
+static const double kMaxVolumeLevel = 255.0;
// Supported hardware sample rates for input and output sides.
#if defined(OS_WIN) || defined(OS_MACOSX)
@@ -46,7 +47,8 @@ WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()
bytes_per_sample_(0),
initialized_(false),
playing_(false),
- recording_(false) {
+ recording_(false),
+ agc_is_enabled_(false) {
DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()";
DCHECK(RenderThreadImpl::current()) <<
"WebRtcAudioDeviceImpl must be constructed on the render thread";
@@ -138,12 +140,12 @@ void WebRtcAudioDeviceImpl::OnRenderError() {
LOG(ERROR) << "OnRenderError()";
}
-void WebRtcAudioDeviceImpl::Capture(
- const std::vector<float*>& audio_data,
- size_t number_of_frames,
- size_t audio_delay_milliseconds) {
+void WebRtcAudioDeviceImpl::Capture(const std::vector<float*>& audio_data,
+ size_t number_of_frames,
+ size_t audio_delay_milliseconds,
+ double volume) {
DCHECK_LE(number_of_frames, input_buffer_size_);
-
+ DCHECK_LE(volume, 1.0);
int output_delay_ms = 0;
{
base::AutoLock auto_lock(lock_);
@@ -171,15 +173,17 @@ void WebRtcAudioDeviceImpl::Capture(
const int bytes_per_10_msec =
channels * samples_per_10_msec * bytes_per_sample_;
size_t accumulated_audio_samples = 0;
-
char* audio_byte_buffer = reinterpret_cast<char*>(input_buffer_.get());
+ // Map internal volume range of [0.0, 1.0] into [0, 255] used by the
+ // webrtc::VoiceEngine.
+ uint32_t current_mic_level = static_cast<uint32_t>(volume * kMaxVolumeLevel);
+
// Write audio samples in blocks of 10 milliseconds to the registered
// webrtc::AudioTransport sink. Keep writing until our internal byte
// buffer is empty.
while (accumulated_audio_samples < number_of_frames) {
- // Deliver 10ms of recorded PCM audio.
- // TODO(henrika): add support for analog AGC?
+ // Deliver 10ms of recorded 16-bit linear PCM audio.
audio_transport_callback_->RecordedDataIsAvailable(
audio_byte_buffer,
samples_per_10_msec,
@@ -187,12 +191,24 @@ void WebRtcAudioDeviceImpl::Capture(
channels,
samples_per_sec,
input_delay_ms_ + output_delay_ms,
- 0, // clock_drift
- 0, // current_mic_level
- new_mic_level); // not used
+ 0, // TODO(henrika): |clock_drift| parameter is not utilized today.
+ current_mic_level,
+ new_mic_level);
+
accumulated_audio_samples += samples_per_10_msec;
audio_byte_buffer += bytes_per_10_msec;
}
+
+ // The AGC returns a non-zero microphone level if it has been decided
scherkus (not reviewing) 2012/03/20 13:49:41 I'm confused -- isn't it the audio_transport_callb
henrika (OOO until Aug 14) 2012/03/21 10:16:04 The last two parameters in RecordedDataIsAvailable
+ // that a new level should be set.
+ if (new_mic_level != 0) {
+ // Use IPC and set the new level. Note that, it will take some time
+ // before the new level is effective due to the IPC scheme.
+ // During this time, |current_mic_level| will contain "non-valid" values
+ // and it might reduce the AGC performance. Measurements on Windows 7 have
+ // shown that we might receive old volume levels for one or two callbacks.
+ SetMicrophoneVolume(new_mic_level);
+ }
}
void WebRtcAudioDeviceImpl::OnCaptureError() {
@@ -677,13 +693,19 @@ bool WebRtcAudioDeviceImpl::Recording() const {
}
int32_t WebRtcAudioDeviceImpl::SetAGC(bool enable) {
- DVLOG(2) << "WARNING: WebRtcAudioDeviceImpl::SetAGC() " << "NOT IMPLEMENTED";
- return -1;
+ // The most common usage is to set the AGC state before recording starts.
+ // The AudioInputDevice also supports changing the AGC state on the fly,
+ // i.e., it is possible to modify the AGC state while audio streaming is
+ // active.
scherkus (not reviewing) 2012/03/21 09:21:21 when you say "most common usage" do you actually m
henrika (OOO until Aug 14) 2012/03/21 10:16:04 I discussed it with Justin and it was OK to add su
+ audio_input_device_->SetAutomaticGainControl(enable);
+ agc_is_enabled_ = enable;
+ return 0;
}
bool WebRtcAudioDeviceImpl::AGC() const {
- DVLOG(2) << "WARNING: WebRtcAudioDeviceImpl::AGC() " << "NOT IMPLEMENTED";
- return false;
+ // To reduce the usage of IPC messages, an internal AGC state is used.
+ // TODO(henrika): investigate if there is a need for a "deeper" getter.
+ return agc_is_enabled_;
}
int32_t WebRtcAudioDeviceImpl::SetWaveOutVolume(uint16_t volume_left,
@@ -756,8 +778,7 @@ int32_t WebRtcAudioDeviceImpl::MaxSpeakerVolume(uint32_t* max_volume) const {
return -1;
}
-int32_t WebRtcAudioDeviceImpl::MinSpeakerVolume(
- uint32_t* min_volume) const {
+int32_t WebRtcAudioDeviceImpl::MinSpeakerVolume(uint32_t* min_volume) const {
NOTIMPLEMENTED();
return -1;
}
@@ -774,32 +795,39 @@ int32_t WebRtcAudioDeviceImpl::MicrophoneVolumeIsAvailable(bool* available) {
}
int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) {
- NOTIMPLEMENTED();
- return -1;
+ DVLOG(1) << "SetMicrophoneVolume(" << volume << ")";
+ if (volume > kMaxVolumeLevel)
+ return -1;
+
+ // WebRTC uses a range of [0, 255] to represent the level of the microphone
+ // volume. The IPC channel between the renderer and browser process works
+ // with doubles in the [0.0, 1.0] range and we have to compensate for that.
+ double normalized_volume = static_cast<double>(volume / kMaxVolumeLevel);
tommi (sloooow) - chröme 2012/03/16 13:31:05 is the cast needed?
henrika (OOO until Aug 14) 2012/03/21 10:16:04 Good question. I don't think is required for funda
+ audio_input_device_->SetVolume(normalized_volume);
+ return 0;
}
int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const {
- NOTIMPLEMENTED();
+ // The microphone level is fed to this class using the Capture() callback
+ // and this external API should not be used. Additional IPC messages are
+ // required if support for this API is ever needed.
+ NOTREACHED();
return -1;
}
-int32_t WebRtcAudioDeviceImpl::MaxMicrophoneVolume(
- uint32_t* max_volume) const {
- DVLOG(2) << "WARNING: WebRtcAudioDeviceImpl::MaxMicrophoneVolume() "
- << "NOT IMPLEMENTED";
- return -1;
+int32_t WebRtcAudioDeviceImpl::MaxMicrophoneVolume(uint32_t* max_volume) const {
+ *max_volume = kMaxVolumeLevel;
+ return 0;
}
-int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(
- uint32_t* min_volume) const {
- DVLOG(2) << "WARNING: WebRtcAudioDeviceImpl::MinMicrophoneVolume() "
- << "NOT IMPLEMENTED";
- return -1;
+int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(uint32_t* min_volume) const {
+ *min_volume = 0;
+ return 0;
}
int32_t WebRtcAudioDeviceImpl::MicrophoneVolumeStepSize(
uint16_t* step_size) const {
- NOTIMPLEMENTED();
+ NOTREACHED();
tommi (sloooow) - chröme 2012/03/16 13:31:05 A comment on why we never expect this to be called
henrika (OOO until Aug 14) 2012/03/21 10:16:04 Good question. It is a method that have caused us
return -1;
}

Powered by Google App Engine
This is Rietveld 408576698