summaryrefslogtreecommitdiff
path: root/voice_engine
diff options
context:
space:
mode:
authorxians@webrtc.org <xians@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2013-07-31 16:27:42 +0000
committerxians@webrtc.org <xians@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2013-07-31 16:27:42 +0000
commit0e6fa8c05cde2587e30dcf5e405132193d60dd42 (patch)
treeea824433142661de81db7aca5a32242fc59c7963 /voice_engine
parent44f1239d9595c91f69f656e5beb1382463c4da8f (diff)
downloadwebrtc-0e6fa8c05cde2587e30dcf5e405132193d60dd42.tar.gz
Merge r4394 from stable to trunk.
r4326 was mistakenly committed to stable, so this is to re-merge back to trunk. Fixed the AGC and interface problems on the new path. In order to make the AGC work properly, we need to cache the volume value passed by the callback, compare it with the value returned by shared->transmit_mixer()->CaptureLevel(). If they are the same, we need to return 0 to indicate no volume needs changing, otherwise return the new volume. By doing this, we avoid setting the volume all the same, which allows the users to change the volume manually. This patch also fixes some minor issues with the interfaces too: make the int channel[] const, and correct the order of the input params in channel::Demultiplex. R=tommi@webrtc.org BUG=[2134] TEST=compile && manual AGC test Review URL: https://webrtc-codereview.appspot.com/1921004 git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@4450 4adac7df-926f-26a2-2b94-8c16560cd09d
Diffstat (limited to 'voice_engine')
-rw-r--r--voice_engine/channel.cc4
-rw-r--r--voice_engine/channel.h4
-rw-r--r--voice_engine/transmit_mixer.cc4
-rw-r--r--voice_engine/transmit_mixer.h4
-rw-r--r--voice_engine/voe_base_impl.cc209
-rw-r--r--voice_engine/voe_base_impl.h20
6 files changed, 130 insertions, 115 deletions
diff --git a/voice_engine/channel.cc b/voice_engine/channel.cc
index d8ee96a1..1a77b7f9 100644
--- a/voice_engine/channel.cc
+++ b/voice_engine/channel.cc
@@ -4422,9 +4422,9 @@ Channel::Demultiplex(const AudioFrame& audioFrame)
// TransmitMixer::GenerateAudioFrame(), refactor these two methods and reduce
// code duplication.
void Channel::Demultiplex(const int16_t* audio_data,
+ int sample_rate,
int number_of_frames,
- int number_of_channels,
- int sample_rate) {
+ int number_of_channels) {
// The highest sample rate that WebRTC supports for mono audio is 96kHz.
static const int kMaxNumberOfFrames = 960;
assert(number_of_frames <= kMaxNumberOfFrames);
diff --git a/voice_engine/channel.h b/voice_engine/channel.h
index 4896f731..444282f4 100644
--- a/voice_engine/channel.h
+++ b/voice_engine/channel.h
@@ -426,9 +426,9 @@ public:
// between this method and the overloaded method above is that |audio_data|
// does not go through transmit_mixer and APM.
void Demultiplex(const int16_t* audio_data,
+ int sample_rate,
int number_of_frames,
- int number_of_channels,
- int sample_rate);
+ int number_of_channels);
uint32_t PrepareEncodeAndSend(int mixingFrequency);
uint32_t EncodeAndSend();
diff --git a/voice_engine/transmit_mixer.cc b/voice_engine/transmit_mixer.cc
index 79d14541..c7c1aaed 100644
--- a/voice_engine/transmit_mixer.cc
+++ b/voice_engine/transmit_mixer.cc
@@ -443,7 +443,7 @@ TransmitMixer::DemuxAndMix()
return 0;
}
-void TransmitMixer::DemuxAndMix(int voe_channels[],
+void TransmitMixer::DemuxAndMix(const int voe_channels[],
int number_of_voe_channels) {
for (int i = 0; i < number_of_voe_channels; ++i) {
voe::ScopedChannel sc(*_channelManagerPtr, voe_channels[i]);
@@ -480,7 +480,7 @@ TransmitMixer::EncodeAndSend()
return 0;
}
-void TransmitMixer::EncodeAndSend(int voe_channels[],
+void TransmitMixer::EncodeAndSend(const int voe_channels[],
int number_of_voe_channels) {
for (int i = 0; i < number_of_voe_channels; ++i) {
voe::ScopedChannel sc(*_channelManagerPtr, voe_channels[i]);
diff --git a/voice_engine/transmit_mixer.h b/voice_engine/transmit_mixer.h
index c68293fe..b7c7403a 100644
--- a/voice_engine/transmit_mixer.h
+++ b/voice_engine/transmit_mixer.h
@@ -63,12 +63,12 @@ public:
int32_t DemuxAndMix();
// Used by the Chrome to pass the recording data to the specific VoE
// channels for demux.
- void DemuxAndMix(int voe_channels[], int number_of_voe_channels);
+ void DemuxAndMix(const int voe_channels[], int number_of_voe_channels);
int32_t EncodeAndSend();
// Used by the Chrome to pass the recording data to the specific VoE
// channels for encoding and sending to the network.
- void EncodeAndSend(int voe_channels[], int number_of_voe_channels);
+ void EncodeAndSend(const int voe_channels[], int number_of_voe_channels);
uint32_t CaptureLevel() const;
diff --git a/voice_engine/voe_base_impl.cc b/voice_engine/voe_base_impl.cc
index c703efda..3dddca56 100644
--- a/voice_engine/voe_base_impl.cc
+++ b/voice_engine/voe_base_impl.cc
@@ -142,91 +142,9 @@ int32_t VoEBaseImpl::RecordedDataIsAvailable(
"totalDelayMS=%u, clockDrift=%d, currentMicLevel=%u)",
nSamples, nBytesPerSample, nChannels, samplesPerSec,
totalDelayMS, clockDrift, currentMicLevel);
-
- assert(_shared->transmit_mixer() != NULL);
- assert(_shared->audio_device() != NULL);
-
- bool isAnalogAGC(false);
- uint32_t maxVolume(0);
- uint16_t currentVoEMicLevel(0);
- uint32_t newVoEMicLevel(0);
-
- if (_shared->audio_processing() &&
- (_shared->audio_processing()->gain_control()->mode()
- == GainControl::kAdaptiveAnalog))
- {
- isAnalogAGC = true;
- }
-
- // Will only deal with the volume in adaptive analog mode
- if (isAnalogAGC)
- {
- // Scale from ADM to VoE level range
- if (_shared->audio_device()->MaxMicrophoneVolume(&maxVolume) == 0)
- {
- if (0 != maxVolume)
- {
- currentVoEMicLevel = (uint16_t) ((currentMicLevel
- * kMaxVolumeLevel + (int) (maxVolume / 2))
- / (maxVolume));
- }
- }
- // We learned that on certain systems (e.g Linux) the currentVoEMicLevel
- // can be greater than the maxVolumeLevel therefore
- // we are going to cap the currentVoEMicLevel to the maxVolumeLevel
- // and change the maxVolume to currentMicLevel if it turns out that
- // the currentVoEMicLevel is indeed greater than the maxVolumeLevel.
- if (currentVoEMicLevel > kMaxVolumeLevel)
- {
- currentVoEMicLevel = kMaxVolumeLevel;
- maxVolume = currentMicLevel;
- }
- }
-
- // Keep track if the MicLevel has been changed by the AGC, if not,
- // use the old value AGC returns to let AGC continue its trend,
- // so eventually the AGC is able to change the mic level. This handles
- // issues with truncation introduced by the scaling.
- if (_oldMicLevel == currentMicLevel)
- {
- currentVoEMicLevel = (uint16_t) _oldVoEMicLevel;
- }
-
- // Perform channel-independent operations
- // (APM, mix with file, record to file, mute, etc.)
- _shared->transmit_mixer()->PrepareDemux(audioSamples, nSamples, nChannels,
- samplesPerSec, static_cast<uint16_t>(totalDelayMS), clockDrift,
- currentVoEMicLevel, keyPressed);
-
- // Copy the audio frame to each sending channel and perform
- // channel-dependent operations (file mixing, mute, etc.) to prepare
- // for encoding.
- _shared->transmit_mixer()->DemuxAndMix();
- // Do the encoding and packetize+transmit the RTP packet when encoding
- // is done.
- _shared->transmit_mixer()->EncodeAndSend();
-
- // Will only deal with the volume in adaptive analog mode
- if (isAnalogAGC)
- {
- // Scale from VoE to ADM level range
- newVoEMicLevel = _shared->transmit_mixer()->CaptureLevel();
- if (newVoEMicLevel != currentVoEMicLevel)
- {
- // Add (kMaxVolumeLevel/2) to round the value
- newMicLevel = (uint32_t) ((newVoEMicLevel * maxVolume
- + (int) (kMaxVolumeLevel / 2)) / (kMaxVolumeLevel));
- }
- else
- {
- // Pass zero if the level is unchanged
- newMicLevel = 0;
- }
-
- // Keep track of the value AGC returns
- _oldVoEMicLevel = newVoEMicLevel;
- _oldMicLevel = currentMicLevel;
- }
+ newMicLevel = static_cast<uint32_t>(ProcessRecordedDataWithAPM(
+ NULL, 0, audioSamples, samplesPerSec, nChannels, nSamples,
+ totalDelayMS, clockDrift, currentMicLevel, keyPressed));
return 0;
}
@@ -274,7 +192,7 @@ int32_t VoEBaseImpl::NeedMorePlayData(
return 0;
}
-int VoEBaseImpl::OnDataAvailable(int voe_channels[],
+int VoEBaseImpl::OnDataAvailable(const int voe_channels[],
int number_of_voe_channels,
const int16_t* audio_data,
int sample_rate,
@@ -292,27 +210,14 @@ int VoEBaseImpl::OnDataAvailable(int voe_channels[],
number_of_voe_channels, sample_rate, number_of_channels,
number_of_frames, audio_delay_milliseconds, current_volume,
key_pressed, need_audio_processing);
+ if (number_of_voe_channels == 0)
+ return 0;
if (need_audio_processing) {
- // Perform channel-independent operations
- // (APM, mix with file, record to file, mute, etc.)
- _shared->transmit_mixer()->PrepareDemux(
- audio_data, number_of_frames, number_of_channels,
- sample_rate, static_cast<uint16_t>(audio_delay_milliseconds), 0,
- current_volume, key_pressed);
- _shared->transmit_mixer()->DemuxAndMix(voe_channels,
- number_of_voe_channels);
- _shared->transmit_mixer()->EncodeAndSend(voe_channels,
- number_of_voe_channels);
- // Update the volume if the analog AGC is working.
- if (_shared->audio_processing() &&
- _shared->audio_processing()->gain_control()->mode() ==
- GainControl::kAdaptiveAnalog) {
- return _shared->transmit_mixer()->CaptureLevel();
- }
-
- // Return 0 to indicate no need to change the volume.
- return 0;
+ return ProcessRecordedDataWithAPM(
+ voe_channels, number_of_voe_channels, audio_data, sample_rate,
+ number_of_channels, number_of_frames, audio_delay_milliseconds,
+ 0, current_volume, key_pressed);
}
// No need to go through the APM, demultiplex the data to each VoE channel,
@@ -1304,4 +1209,98 @@ int32_t VoEBaseImpl::TerminateInternal()
return _shared->statistics().SetUnInitialized();
}
+int VoEBaseImpl::ProcessRecordedDataWithAPM(
+ const int voe_channels[],
+ int number_of_voe_channels,
+ const void* audio_data,
+ uint32_t sample_rate,
+ uint8_t number_of_channels,
+ uint32_t number_of_frames,
+ uint32_t audio_delay_milliseconds,
+ int32_t clock_drift,
+ uint32_t current_volume,
+ bool key_pressed) {
+ assert(_shared->transmit_mixer() != NULL);
+ assert(_shared->audio_device() != NULL);
+
+ bool is_analog_agc(false);
+ if (_shared->audio_processing() &&
+ _shared->audio_processing()->gain_control()->mode() ==
+ GainControl::kAdaptiveAnalog) {
+ is_analog_agc = true;
+ }
+
+ // Only deal with the volume in adaptive analog mode.
+ uint32_t max_volume = 0;
+ uint16_t current_voe_mic_level = 0;
+ if (is_analog_agc) {
+ // Scale from ADM to VoE level range
+ if (_shared->audio_device()->MaxMicrophoneVolume(&max_volume) == 0) {
+ if (max_volume) {
+ current_voe_mic_level = static_cast<uint16_t>(
+ (current_volume * kMaxVolumeLevel +
+ static_cast<int>(max_volume / 2)) / max_volume);
+ }
+ }
+ // We learned that on certain systems (e.g Linux) the current_voe_mic_level
+ // can be greater than the maxVolumeLevel therefore
+ // we are going to cap the current_voe_mic_level to the maxVolumeLevel
+ // and change the maxVolume to current_volume if it turns out that
+ // the current_voe_mic_level is indeed greater than the maxVolumeLevel.
+ if (current_voe_mic_level > kMaxVolumeLevel) {
+ current_voe_mic_level = kMaxVolumeLevel;
+ max_volume = current_volume;
+ }
+ }
+
+ // Keep track if the MicLevel has been changed by the AGC, if not,
+ // use the old value AGC returns to let AGC continue its trend,
+ // so eventually the AGC is able to change the mic level. This handles
+ // issues with truncation introduced by the scaling.
+ if (_oldMicLevel == current_volume)
+ current_voe_mic_level = static_cast<uint16_t>(_oldVoEMicLevel);
+
+ // Perform channel-independent operations
+ // (APM, mix with file, record to file, mute, etc.)
+ _shared->transmit_mixer()->PrepareDemux(
+ audio_data, number_of_frames, number_of_channels, sample_rate,
+ static_cast<uint16_t>(audio_delay_milliseconds), clock_drift,
+ current_voe_mic_level, key_pressed);
+
+ // Copy the audio frame to each sending channel and perform
+ // channel-dependent operations (file mixing, mute, etc.), encode and
+ // packetize+transmit the RTP packet. When |number_of_voe_channels| == 0,
+ // do the operations on all the existing VoE channels; otherwise the
+ // operations will be done on specific channels.
+ if (number_of_voe_channels == 0) {
+ _shared->transmit_mixer()->DemuxAndMix();
+ _shared->transmit_mixer()->EncodeAndSend();
+ } else {
+ _shared->transmit_mixer()->DemuxAndMix(voe_channels,
+ number_of_voe_channels);
+ _shared->transmit_mixer()->EncodeAndSend(voe_channels,
+ number_of_voe_channels);
+ }
+
+ if (!is_analog_agc)
+ return 0;
+
+ // Scale from VoE to ADM level range.
+ uint32_t new_voe_mic_level = _shared->transmit_mixer()->CaptureLevel();
+
+ // Keep track of the value AGC returns.
+ _oldVoEMicLevel = new_voe_mic_level;
+ _oldMicLevel = current_volume;
+
+ if (new_voe_mic_level != current_voe_mic_level) {
+ // Return the new volume if AGC has changed the volume.
+ return static_cast<int>(
+ (new_voe_mic_level * max_volume +
+ static_cast<int>(kMaxVolumeLevel / 2)) / kMaxVolumeLevel);
+ }
+
+ // Return 0 to indicate no change on the volume.
+ return 0;
+}
+
} // namespace webrtc
diff --git a/voice_engine/voe_base_impl.h b/voice_engine/voe_base_impl.h
index c63798f3..b192ca20 100644
--- a/voice_engine/voe_base_impl.h
+++ b/voice_engine/voe_base_impl.h
@@ -90,7 +90,7 @@ public:
void* audioSamples,
uint32_t& nSamplesOut);
- virtual int OnDataAvailable(int voe_channels[],
+ virtual int OnDataAvailable(const int voe_channels[],
int number_of_voe_channels,
const int16_t* audio_data,
int sample_rate,
@@ -116,6 +116,23 @@ private:
int32_t StopSend();
int32_t TerminateInternal();
+ // Helper function to process the recorded data with AudioProcessing Module,
+ // demultiplex the data to specific voe channels, encode and send to the
+ // network. When |number_of_VoE_channels| is 0, it will demultiplex the
+ // data to all the existing VoE channels.
+ // It returns new AGC microphone volume or 0 if no volume changes
+ // should be done.
+ int ProcessRecordedDataWithAPM(const int voe_channels[],
+ int number_of_voe_channels,
+ const void* audio_data,
+ uint32_t sample_rate,
+ uint8_t number_of_channels,
+ uint32_t number_of_frames,
+ uint32_t audio_delay_milliseconds,
+ int32_t clock_drift,
+ uint32_t current_volume,
+ bool key_pressed);
+
int32_t AddBuildInfo(char* str) const;
int32_t AddVoEVersion(char* str) const;
#ifdef WEBRTC_EXTERNAL_TRANSPORT
@@ -132,7 +149,6 @@ private:
uint32_t _oldMicLevel;
AudioFrame _audioFrame;
voe::SharedData* _shared;
-
};
} // namespace webrtc