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

Side by Side Diff: content/browser/speech/speech_recognizer.cc

Issue 6597071: Add a noise indicator to the speech bubble volume indicator. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed all review comments. Created 9 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "content/browser/speech/speech_recognizer.h" 5 #include "content/browser/speech/speech_recognizer.h"
6 6
7 #include "base/time.h" 7 #include "base/time.h"
8 #include "chrome/browser/profiles/profile.h" 8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/common/net/url_request_context_getter.h" 9 #include "chrome/common/net/url_request_context_getter.h"
10 #include "content/browser/browser_thread.h" 10 #include "content/browser/browser_thread.h"
11 11
12 using media::AudioInputController; 12 using media::AudioInputController;
13 using std::string; 13 using std::string;
14 14
15 namespace { 15 namespace {
16 16
17 // The following constants are related to the volume level indicator shown in 17 // The following constants are related to the volume level indicator shown in
18 // the UI for recorded audio. 18 // the UI for recorded audio.
19 // Multiplier used when new volume is greater than previous level. 19 // Multiplier used when new volume is greater than previous level.
20 const float kUpSmoothingFactor = 0.9f; 20 const float kUpSmoothingFactor = 1.0f;
21 // Multiplier used when new volume is lesser than previous level. 21 // Multiplier used when new volume is lesser than previous level.
22 const float kDownSmoothingFactor = 0.4f; 22 const float kDownSmoothingFactor = 0.7f;
23 const float kAudioMeterMinDb = 10.0f; // Lower bar for volume meter. 23 // RMS dB value of a maximum (unclipped) sine wave for int16 samples.
24 const float kAudioMeterDbRange = 25.0f; 24 const float kAudioMeterMaxDb = 90.31f;
25 // This value corresponds to RMS dB for int16 with 6 most-significant-bits = 0.
26 // Values lower than this will display as empty level-meter.
27 const float kAudioMeterMinDb = 60.21f;
28 const float kAudioMeterDbRange = kAudioMeterMaxDb - kAudioMeterMinDb;
29
30 // Maximum level to draw to display unclipped meter. (1.0f displays clipping.)
31 const float kAudioMeterRangeMaxUnclipped = 47.0f / 48.0f;
32
33 // Returns true if more than 5% of the samples are at min or max value.
34 bool Clipping(const int16* samples, int num_samples) {
35 int clipping_samples = 0;
36 const int kThreshold = num_samples / 20;
37 for (int i = 0; i < num_samples; ++i) {
38 if (samples[i] <= -32767 || samples[i] >= 32767) {
39 if (++clipping_samples > kThreshold)
40 return true;
41 }
42 }
43 return false;
44 }
45
25 } // namespace 46 } // namespace
26 47
27 namespace speech_input { 48 namespace speech_input {
28 49
29 const int SpeechRecognizer::kAudioSampleRate = 16000; 50 const int SpeechRecognizer::kAudioSampleRate = 16000;
30 const int SpeechRecognizer::kAudioPacketIntervalMs = 100; 51 const int SpeechRecognizer::kAudioPacketIntervalMs = 100;
31 const int SpeechRecognizer::kNumAudioChannels = 1; 52 const int SpeechRecognizer::kNumAudioChannels = 1;
32 const int SpeechRecognizer::kNumBitsPerAudioSample = 16; 53 const int SpeechRecognizer::kNumBitsPerAudioSample = 16;
33 const int SpeechRecognizer::kNoSpeechTimeoutSec = 8; 54 const int SpeechRecognizer::kNoSpeechTimeoutSec = 8;
34 const int SpeechRecognizer::kEndpointerEstimationTimeMs = 300; 55 const int SpeechRecognizer::kEndpointerEstimationTimeMs = 300;
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 234
214 // Check if we have waited too long without hearing any speech. 235 // Check if we have waited too long without hearing any speech.
215 if (!endpointer_.DidStartReceivingSpeech() && 236 if (!endpointer_.DidStartReceivingSpeech() &&
216 num_samples_recorded_ >= kNoSpeechTimeoutSec * kAudioSampleRate) { 237 num_samples_recorded_ >= kNoSpeechTimeoutSec * kAudioSampleRate) {
217 InformErrorAndCancelRecognition(RECOGNIZER_ERROR_NO_SPEECH); 238 InformErrorAndCancelRecognition(RECOGNIZER_ERROR_NO_SPEECH);
218 return; 239 return;
219 } 240 }
220 241
221 // Calculate the input volume to display in the UI, smoothing towards the 242 // Calculate the input volume to display in the UI, smoothing towards the
222 // new level. 243 // new level.
223 float level = (rms - kAudioMeterMinDb) / kAudioMeterDbRange; 244 float level = (rms - kAudioMeterMinDb) /
224 level = std::min(std::max(0.0f, level), 1.0f); 245 (kAudioMeterDbRange / kAudioMeterRangeMaxUnclipped);
246 level = std::min(std::max(0.0f, level), kAudioMeterRangeMaxUnclipped);
225 if (level > audio_level_) { 247 if (level > audio_level_) {
226 audio_level_ += (level - audio_level_) * kUpSmoothingFactor; 248 audio_level_ += (level - audio_level_) * kUpSmoothingFactor;
227 } else { 249 } else {
228 audio_level_ += (level - audio_level_) * kDownSmoothingFactor; 250 audio_level_ += (level - audio_level_) * kDownSmoothingFactor;
229 } 251 }
230 delegate_->SetInputVolume(caller_id_, audio_level_); 252
253 float noise_level = (endpointer_.NoiseLevelDb() - kAudioMeterMinDb) /
254 (kAudioMeterDbRange / kAudioMeterRangeMaxUnclipped);
255 noise_level = std::min(std::max(0.0f, noise_level),
256 kAudioMeterRangeMaxUnclipped);
257
258 delegate_->SetInputVolume(caller_id_,
259 Clipping(samples, num_samples) ? 1.0f : audio_level_, noise_level);
231 260
232 if (endpointer_.speech_input_complete()) { 261 if (endpointer_.speech_input_complete()) {
233 StopRecording(); 262 StopRecording();
234 } 263 }
235 264
236 // TODO(satish): Once we have streaming POST, start sending the data received 265 // TODO(satish): Once we have streaming POST, start sending the data received
237 // here as POST chunks. 266 // here as POST chunks.
238 } 267 }
239 268
240 void SpeechRecognizer::SetRecognitionResult( 269 void SpeechRecognizer::SetRecognitionResult(
(...skipping 12 matching lines...) Expand all
253 282
254 void SpeechRecognizer::InformErrorAndCancelRecognition(ErrorCode error) { 283 void SpeechRecognizer::InformErrorAndCancelRecognition(ErrorCode error) {
255 CancelRecognition(); 284 CancelRecognition();
256 285
257 // Guard against the delegate freeing us until we finish our job. 286 // Guard against the delegate freeing us until we finish our job.
258 scoped_refptr<SpeechRecognizer> me(this); 287 scoped_refptr<SpeechRecognizer> me(this);
259 delegate_->OnRecognizerError(caller_id_, error); 288 delegate_->OnRecognizerError(caller_id_, error);
260 } 289 }
261 290
262 } // namespace speech_input 291 } // namespace speech_input
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698