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

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: . 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 for (int i = 0; i < num_samples; ++i) {
37 if (samples[i] <= -32767 || samples[i] >= 32767) {
38 ++clipping_samples;
bulach 2011/03/01 17:39:04 you may want to short circuit rather than traverse
39 }
40 }
41 return clipping_samples > (num_samples / 20);
42 }
43
25 } // namespace 44 } // namespace
26 45
27 namespace speech_input { 46 namespace speech_input {
28 47
29 const int SpeechRecognizer::kAudioSampleRate = 16000; 48 const int SpeechRecognizer::kAudioSampleRate = 16000;
30 const int SpeechRecognizer::kAudioPacketIntervalMs = 100; 49 const int SpeechRecognizer::kAudioPacketIntervalMs = 100;
31 const int SpeechRecognizer::kNumAudioChannels = 1; 50 const int SpeechRecognizer::kNumAudioChannels = 1;
32 const int SpeechRecognizer::kNumBitsPerAudioSample = 16; 51 const int SpeechRecognizer::kNumBitsPerAudioSample = 16;
33 const int SpeechRecognizer::kNoSpeechTimeoutSec = 8; 52 const int SpeechRecognizer::kNoSpeechTimeoutSec = 8;
34 const int SpeechRecognizer::kEndpointerEstimationTimeMs = 300; 53 const int SpeechRecognizer::kEndpointerEstimationTimeMs = 300;
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 232
214 // Check if we have waited too long without hearing any speech. 233 // Check if we have waited too long without hearing any speech.
215 if (!endpointer_.DidStartReceivingSpeech() && 234 if (!endpointer_.DidStartReceivingSpeech() &&
216 num_samples_recorded_ >= kNoSpeechTimeoutSec * kAudioSampleRate) { 235 num_samples_recorded_ >= kNoSpeechTimeoutSec * kAudioSampleRate) {
217 InformErrorAndCancelRecognition(RECOGNIZER_ERROR_NO_SPEECH); 236 InformErrorAndCancelRecognition(RECOGNIZER_ERROR_NO_SPEECH);
218 return; 237 return;
219 } 238 }
220 239
221 // Calculate the input volume to display in the UI, smoothing towards the 240 // Calculate the input volume to display in the UI, smoothing towards the
222 // new level. 241 // new level.
223 float level = (rms - kAudioMeterMinDb) / kAudioMeterDbRange; 242 float level = (rms - kAudioMeterMinDb) /
224 level = std::min(std::max(0.0f, level), 1.0f); 243 (kAudioMeterDbRange / kAudioMeterRangeMaxUnclipped);
244 level = std::min(std::max(0.0f, level), kAudioMeterRangeMaxUnclipped);
225 if (level > audio_level_) { 245 if (level > audio_level_) {
226 audio_level_ += (level - audio_level_) * kUpSmoothingFactor; 246 audio_level_ += (level - audio_level_) * kUpSmoothingFactor;
227 } else { 247 } else {
228 audio_level_ += (level - audio_level_) * kDownSmoothingFactor; 248 audio_level_ += (level - audio_level_) * kDownSmoothingFactor;
229 } 249 }
230 delegate_->SetInputVolume(caller_id_, audio_level_); 250
251 float noise_level = (endpointer_.NoiseLevelDB() - kAudioMeterMinDb) /
252 (kAudioMeterDbRange / kAudioMeterRangeMaxUnclipped);
253 noise_level = std::min(std::max(0.0f, noise_level),
254 kAudioMeterRangeMaxUnclipped);
255
256 delegate_->SetInputVolume(caller_id_,
257 Clipping(samples, num_samples) ? 1.0f : audio_level_, noise_level);
231 258
232 if (endpointer_.speech_input_complete()) { 259 if (endpointer_.speech_input_complete()) {
233 StopRecording(); 260 StopRecording();
234 } 261 }
235 262
236 // TODO(satish): Once we have streaming POST, start sending the data received 263 // TODO(satish): Once we have streaming POST, start sending the data received
237 // here as POST chunks. 264 // here as POST chunks.
238 } 265 }
239 266
240 void SpeechRecognizer::SetRecognitionResult( 267 void SpeechRecognizer::SetRecognitionResult(
(...skipping 12 matching lines...) Expand all
253 280
254 void SpeechRecognizer::InformErrorAndCancelRecognition(ErrorCode error) { 281 void SpeechRecognizer::InformErrorAndCancelRecognition(ErrorCode error) {
255 CancelRecognition(); 282 CancelRecognition();
256 283
257 // Guard against the delegate freeing us until we finish our job. 284 // Guard against the delegate freeing us until we finish our job.
258 scoped_refptr<SpeechRecognizer> me(this); 285 scoped_refptr<SpeechRecognizer> me(this);
259 delegate_->OnRecognizerError(caller_id_, error); 286 delegate_->OnRecognizerError(caller_id_, error);
260 } 287 }
261 288
262 } // namespace speech_input 289 } // namespace speech_input
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698