| Index: content/browser/speech/speech_recognizer.cc
|
| diff --git a/content/browser/speech/speech_recognizer.cc b/content/browser/speech/speech_recognizer.cc
|
| index fdc1a4c5fcba25cf1299144fced0d6094dc30a21..b23f4b0ec7b5b2a9da86354adacfc53915f2d802 100644
|
| --- a/content/browser/speech/speech_recognizer.cc
|
| +++ b/content/browser/speech/speech_recognizer.cc
|
| @@ -17,11 +17,32 @@ namespace {
|
| // The following constants are related to the volume level indicator shown in
|
| // the UI for recorded audio.
|
| // Multiplier used when new volume is greater than previous level.
|
| -const float kUpSmoothingFactor = 0.9f;
|
| +const float kUpSmoothingFactor = 1.0f;
|
| // Multiplier used when new volume is lesser than previous level.
|
| -const float kDownSmoothingFactor = 0.4f;
|
| -const float kAudioMeterMinDb = 10.0f; // Lower bar for volume meter.
|
| -const float kAudioMeterDbRange = 25.0f;
|
| +const float kDownSmoothingFactor = 0.7f;
|
| +// RMS dB value of a maximum (unclipped) sine wave for int16 samples.
|
| +const float kAudioMeterMaxDb = 90.31f;
|
| +// This value corresponds to RMS dB for int16 with 6 most-significant-bits = 0.
|
| +// Values lower than this will display as empty level-meter.
|
| +const float kAudioMeterMinDb = 60.21f;
|
| +const float kAudioMeterDbRange = kAudioMeterMaxDb - kAudioMeterMinDb;
|
| +
|
| +// Maximum level to draw to display unclipped meter. (1.0f displays clipping.)
|
| +const float kAudioMeterRangeMaxUnclipped = 47.0f / 48.0f;
|
| +
|
| +// Returns true if more than 5% of the samples are at min or max value.
|
| +bool Clipping(const int16* samples, int num_samples) {
|
| + int clipping_samples = 0;
|
| + const int kThreshold = num_samples / 20;
|
| + for (int i = 0; i < num_samples; ++i) {
|
| + if (samples[i] <= -32767 || samples[i] >= 32767) {
|
| + if (++clipping_samples > kThreshold)
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| } // namespace
|
|
|
| namespace speech_input {
|
| @@ -220,14 +241,22 @@ void SpeechRecognizer::HandleOnData(string* data) {
|
|
|
| // Calculate the input volume to display in the UI, smoothing towards the
|
| // new level.
|
| - float level = (rms - kAudioMeterMinDb) / kAudioMeterDbRange;
|
| - level = std::min(std::max(0.0f, level), 1.0f);
|
| + float level = (rms - kAudioMeterMinDb) /
|
| + (kAudioMeterDbRange / kAudioMeterRangeMaxUnclipped);
|
| + level = std::min(std::max(0.0f, level), kAudioMeterRangeMaxUnclipped);
|
| if (level > audio_level_) {
|
| audio_level_ += (level - audio_level_) * kUpSmoothingFactor;
|
| } else {
|
| audio_level_ += (level - audio_level_) * kDownSmoothingFactor;
|
| }
|
| - delegate_->SetInputVolume(caller_id_, audio_level_);
|
| +
|
| + float noise_level = (endpointer_.NoiseLevelDb() - kAudioMeterMinDb) /
|
| + (kAudioMeterDbRange / kAudioMeterRangeMaxUnclipped);
|
| + noise_level = std::min(std::max(0.0f, noise_level),
|
| + kAudioMeterRangeMaxUnclipped);
|
| +
|
| + delegate_->SetInputVolume(caller_id_,
|
| + Clipping(samples, num_samples) ? 1.0f : audio_level_, noise_level);
|
|
|
| if (endpointer_.speech_input_complete()) {
|
| StopRecording();
|
|
|