diff options
| author | satish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-01 18:38:36 +0000 |
|---|---|---|
| committer | satish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-01 18:38:36 +0000 |
| commit | 3b283d6e8c6285efde6a1a34273a3bdb9061bd44 (patch) | |
| tree | 9c221cc4d11dacf4f20e9c05287fde698d6721c6 | |
| parent | 229fa74de71e0771f734cc788063515da62f30b4 (diff) | |
| download | chromium_src-3b283d6e8c6285efde6a1a34273a3bdb9061bd44.zip chromium_src-3b283d6e8c6285efde6a1a34273a3bdb9061bd44.tar.gz chromium_src-3b283d6e8c6285efde6a1a34273a3bdb9061bd44.tar.bz2 | |
Add a noise indicator to the speech bubble volume indicator.
The noise indicator is drawn as a light blue area at the beginning and if there
was clipping that is denoted with a red area at the end of the meter. The noise
level comes from the endpointer -> SpeechRecognizer -> SpeechInputBubbleController -> SpeechInputBubble
hence a bunch of volume setting methods are updated with the new parameter.
I have also added a new utility method to SpeechInputManager to invoke the platform
provided microphone settings UI, this will be used in the next CL which contains
windows, mac and linux specific UI changes.
BUG=69886
TEST=manual, invoke speech input and check the bubble volume indicator to see background noise and clipping.
Review URL: http://codereview.chromium.org/6597071
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76395 0039d316-1c4b-4281-b951-d872f2087c98
| -rw-r--r-- | chrome/app/theme/theme_resources.grd | 1 | ||||
| -rw-r--r-- | chrome/browser/speech/speech_input_bubble.cc | 48 | ||||
| -rw-r--r-- | chrome/browser/speech/speech_input_bubble.h | 13 | ||||
| -rw-r--r-- | chrome/browser/speech/speech_input_bubble_controller.cc | 20 | ||||
| -rw-r--r-- | chrome/browser/speech/speech_input_bubble_controller.h | 5 | ||||
| -rw-r--r-- | chrome/browser/speech/speech_input_manager.cc | 24 | ||||
| -rw-r--r-- | content/browser/speech/endpointer/endpointer.h | 3 | ||||
| -rw-r--r-- | content/browser/speech/endpointer/energy_endpointer.cc | 18 | ||||
| -rw-r--r-- | content/browser/speech/endpointer/energy_endpointer.h | 3 | ||||
| -rw-r--r-- | content/browser/speech/speech_input_manager.h | 4 | ||||
| -rw-r--r-- | content/browser/speech/speech_recognizer.cc | 43 | ||||
| -rw-r--r-- | content/browser/speech/speech_recognizer.h | 5 | ||||
| -rw-r--r-- | content/browser/speech/speech_recognizer_unittest.cc | 19 |
13 files changed, 151 insertions, 55 deletions
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 59c7114..d9cae29 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd @@ -367,6 +367,7 @@ <include name="IDR_SETTINGS_FAVICON" file="settings_favicon.png" type="BINDATA" /> <include name="IDR_SIDETABS_NEW_TAB" file="sidetabs_new_tab.png" type="BINDATA" /> <include name="IDR_SPEECH_INPUT_MIC_EMPTY" file="speech_input_mic_empty.png" type="BINDATA" /> + <include name="IDR_SPEECH_INPUT_MIC_NOISE" file="speech_input_mic_noise.png" type="BINDATA" /> <include name="IDR_SPEECH_INPUT_MIC_FULL" file="speech_input_mic_full.png" type="BINDATA" /> <include name="IDR_SPEECH_INPUT_MIC_MASK" file="speech_input_mic_mask.png" type="BINDATA" /> <include name="IDR_SPEECH_INPUT_SPINNER" file="speech_input_spinner.png" type="BINDATA" /> diff --git a/chrome/browser/speech/speech_input_bubble.cc b/chrome/browser/speech/speech_input_bubble.cc index 59cfd45..111eaef 100644 --- a/chrome/browser/speech/speech_input_bubble.cc +++ b/chrome/browser/speech/speech_input_bubble.cc @@ -11,9 +11,10 @@ #include "ui/gfx/rect.h" SpeechInputBubble::FactoryMethod SpeechInputBubble::factory_ = NULL; -const int SpeechInputBubble::kBubbleTargetOffsetX = 5; +const int SpeechInputBubble::kBubbleTargetOffsetX = 10; SkBitmap* SpeechInputBubbleBase::mic_empty_ = NULL; +SkBitmap* SpeechInputBubbleBase::mic_noise_ = NULL; SkBitmap* SpeechInputBubbleBase::mic_full_ = NULL; SkBitmap* SpeechInputBubbleBase::mic_mask_ = NULL; SkBitmap* SpeechInputBubbleBase::spinner_ = NULL; @@ -39,6 +40,8 @@ SpeechInputBubbleBase::SpeechInputBubbleBase(TabContents* tab_contents) if (!mic_empty_) { // Static variables. mic_empty_ = ResourceBundle::GetSharedInstance().GetBitmapNamed( IDR_SPEECH_INPUT_MIC_EMPTY); + mic_noise_ = ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_SPEECH_INPUT_MIC_NOISE); mic_full_ = ResourceBundle::GetSharedInstance().GetBitmapNamed( IDR_SPEECH_INPUT_MIC_FULL); mic_mask_ = ResourceBundle::GetSharedInstance().GetBitmapNamed( @@ -93,14 +96,9 @@ void SpeechInputBubbleBase::SetRecordingMode() { void SpeechInputBubbleBase::SetRecognizingMode() { display_mode_ = DISPLAY_MODE_RECOGNIZING; - UpdateLayout(); - animation_step_ = 0; - MessageLoop::current()->PostDelayedTask( - FROM_HERE, - task_factory_.NewRunnableMethod( - &SpeechInputBubbleBase::DoRecognizingAnimationStep), - kRecognizingAnimationStepMs); + DoRecognizingAnimationStep(); + UpdateLayout(); } void SpeechInputBubbleBase::DoRecognizingAnimationStep() { @@ -121,31 +119,39 @@ void SpeechInputBubbleBase::SetMessage(const string16& text) { UpdateLayout(); } -void SpeechInputBubbleBase::SetInputVolume(float volume) { - mic_image_->eraseARGB(0, 0, 0, 0); +void SpeechInputBubbleBase::DrawVolumeOverlay(SkCanvas* canvas, + const SkBitmap& bitmap, + float volume) { buffer_image_->eraseARGB(0, 0, 0, 0); int width = mic_image_->width(); int height = mic_image_->height(); - SkCanvas canvas(*mic_image_); SkCanvas buffer_canvas(*buffer_image_); - // The 'full volume' mic image is drawn clipped to the current volume level, - // and a gradient mask is applied over it with the 'multiply' compositing - // operator to show soft edges at the top. buffer_canvas.save(); - SkScalar clip_top = ((1.0f - volume) * height * 3) / 2.0f - height / 2.0f; - buffer_canvas.clipRect(SkRect::MakeLTRB(0, clip_top, - SkIntToScalar(width), SkIntToScalar(height))); - buffer_canvas.drawBitmap(*mic_full_, 0, 0); + const int kVolumeSteps = 12; + SkScalar clip_right = + (((1.0f - volume) * (width * (kVolumeSteps + 1))) - width) / kVolumeSteps; + buffer_canvas.clipRect(SkRect::MakeLTRB(0, 0, + SkIntToScalar(width) - clip_right, SkIntToScalar(height))); + buffer_canvas.drawBitmap(bitmap, 0, 0); buffer_canvas.restore(); SkPaint multiply_paint; multiply_paint.setXfermode(SkXfermode::Create(SkXfermode::kMultiply_Mode)); - buffer_canvas.drawBitmap(*mic_mask_, 0, clip_top, &multiply_paint); + buffer_canvas.drawBitmap(*mic_mask_, -clip_right, 0, &multiply_paint); + + canvas->drawBitmap(*buffer_image_.get(), 0, 0); +} + +void SpeechInputBubbleBase::SetInputVolume(float volume, float noise_volume) { + mic_image_->eraseARGB(0, 0, 0, 0); + SkCanvas canvas(*mic_image_); - // Draw the empty volume image first and the current volume image on top. + // Draw the empty volume image first and the current volume image on top, + // and then the noise volume image on top of both. canvas.drawBitmap(*mic_empty_, 0, 0); - canvas.drawBitmap(*buffer_image_.get(), 0, 0); + DrawVolumeOverlay(&canvas, *mic_full_, volume); + DrawVolumeOverlay(&canvas, *mic_noise_, noise_volume); SetImage(*mic_image_.get()); } diff --git a/chrome/browser/speech/speech_input_bubble.h b/chrome/browser/speech/speech_input_bubble.h index dd5d21b..65e0cf4 100644 --- a/chrome/browser/speech/speech_input_bubble.h +++ b/chrome/browser/speech/speech_input_bubble.h @@ -13,9 +13,11 @@ #include "base/task.h" namespace gfx { +class Canvas; class Rect; } class SkBitmap; +class SkCanvas; class TabContents; // SpeechInputBubble displays a popup info bubble during speech recognition, @@ -96,8 +98,8 @@ class SpeechInputBubble { // |Delegate::InfoBubbleFocusChanged| as well. virtual void Hide() = 0; - // Updates the current captured audio volume displayed on screen. - virtual void SetInputVolume(float volume) = 0; + // Updates and draws the current captured audio volume displayed on screen. + virtual void SetInputVolume(float volume, float noise_volume) = 0; // Returns the TabContents for which this bubble gets displayed. virtual TabContents* tab_contents() = 0; @@ -129,7 +131,7 @@ class SpeechInputBubbleBase : public SpeechInputBubble { virtual void SetRecordingMode(); virtual void SetRecognizingMode(); virtual void SetMessage(const string16& text); - virtual void SetInputVolume(float volume); + virtual void SetInputVolume(float volume, float noise_volume); virtual TabContents* tab_contents(); protected: @@ -152,6 +154,10 @@ class SpeechInputBubbleBase : public SpeechInputBubble { private: void DoRecognizingAnimationStep(); + void DrawVolumeOverlay(SkCanvas* canvas, + const SkBitmap& bitmap, + float volume); + // Task factory used for animation timer. ScopedRunnableMethodFactory<SpeechInputBubbleBase> task_factory_; int animation_step_; // Current index/step of the animation. @@ -167,6 +173,7 @@ class SpeechInputBubbleBase : public SpeechInputBubble { TabContents* tab_contents_; static SkBitmap* mic_full_; // Mic image with full volume. + static SkBitmap* mic_noise_; // Mic image with full noise volume. static SkBitmap* mic_empty_; // Mic image with zero volume. static SkBitmap* mic_mask_; // Gradient mask used by the volume indicator. static SkBitmap* spinner_; // Spinner image for the progress animation. diff --git a/chrome/browser/speech/speech_input_bubble_controller.cc b/chrome/browser/speech/speech_input_bubble_controller.cc index 77a32a4..58bda78 100644 --- a/chrome/browser/speech/speech_input_bubble_controller.cc +++ b/chrome/browser/speech/speech_input_bubble_controller.cc @@ -52,28 +52,29 @@ void SpeechInputBubbleController::CreateBubble(int caller_id, } void SpeechInputBubbleController::CloseBubble(int caller_id) { - ProcessRequestInUiThread(caller_id, REQUEST_CLOSE, string16(), 0); + ProcessRequestInUiThread(caller_id, REQUEST_CLOSE, string16(), 0, 0); } void SpeechInputBubbleController::SetBubbleRecordingMode(int caller_id) { ProcessRequestInUiThread(caller_id, REQUEST_SET_RECORDING_MODE, - string16(), 0); + string16(), 0, 0); } void SpeechInputBubbleController::SetBubbleRecognizingMode(int caller_id) { ProcessRequestInUiThread(caller_id, REQUEST_SET_RECOGNIZING_MODE, - string16(), 0); + string16(), 0, 0); } void SpeechInputBubbleController::SetBubbleInputVolume(int caller_id, - float volume) { + float volume, + float noise_volume) { ProcessRequestInUiThread(caller_id, REQUEST_SET_INPUT_VOLUME, string16(), - volume); + volume, noise_volume); } void SpeechInputBubbleController::SetBubbleMessage(int caller_id, const string16& text) { - ProcessRequestInUiThread(caller_id, REQUEST_SET_MESSAGE, text, 0); + ProcessRequestInUiThread(caller_id, REQUEST_SET_MESSAGE, text, 0, 0); } void SpeechInputBubbleController::UpdateTabContentsSubscription( @@ -131,11 +132,12 @@ void SpeechInputBubbleController::Observe(NotificationType type, } void SpeechInputBubbleController::ProcessRequestInUiThread( - int caller_id, RequestType type, const string16& text, float volume) { + int caller_id, RequestType type, const string16& text, float volume, + float noise_volume) { if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod( this, &SpeechInputBubbleController::ProcessRequestInUiThread, - caller_id, type, text, volume)); + caller_id, type, text, volume, noise_volume)); return; } DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -164,7 +166,7 @@ void SpeechInputBubbleController::ProcessRequestInUiThread( bubble->SetMessage(text); break; case REQUEST_SET_INPUT_VOLUME: - bubble->SetInputVolume(volume); + bubble->SetInputVolume(volume, noise_volume); break; case REQUEST_CLOSE: if (current_bubble_caller_id_ == caller_id) diff --git a/chrome/browser/speech/speech_input_bubble_controller.h b/chrome/browser/speech/speech_input_bubble_controller.h index 04c92b5..cdfe5c3 100644 --- a/chrome/browser/speech/speech_input_bubble_controller.h +++ b/chrome/browser/speech/speech_input_bubble_controller.h @@ -68,7 +68,7 @@ class SpeechInputBubbleController void SetBubbleMessage(int caller_id, const string16& text); // Updates the current captured audio volume displayed on screen. - void SetBubbleInputVolume(int caller_id, float volume); + void SetBubbleInputVolume(int caller_id, float volume, float noise_volume); void CloseBubble(int caller_id); @@ -102,7 +102,8 @@ class SpeechInputBubbleController void ProcessRequestInUiThread(int caller_id, RequestType type, const string16& text, - float volume); + float volume, + float noise_volume); // Called whenever a bubble was added to or removed from the list. If the // bubble was being added, this method registers for close notifications with diff --git a/chrome/browser/speech/speech_input_manager.cc b/chrome/browser/speech/speech_input_manager.cc index 626bf4f..141ed21 100644 --- a/chrome/browser/speech/speech_input_manager.cc +++ b/chrome/browser/speech/speech_input_manager.cc @@ -14,6 +14,7 @@ #include "base/threading/thread_restrictions.h" #include "base/utf_string_conversions.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_thread.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/speech/speech_input_bubble_controller.h" @@ -120,7 +121,7 @@ class SpeechInputManagerImpl : public SpeechInputManager, virtual void OnRecognizerError(int caller_id, SpeechRecognizer::ErrorCode error); virtual void DidCompleteEnvironmentEstimation(int caller_id); - virtual void SetInputVolume(int caller_id, float volume); + virtual void SetInputVolume(int caller_id, float volume, float noise_volume); // SpeechInputBubbleController::Delegate methods. virtual void InfoBubbleButtonClicked(int caller_id, @@ -183,6 +184,22 @@ bool SpeechInputManager::IsFeatureEnabled() { return enabled; } +void SpeechInputManager::ShowAudioInputSettings() { + // Since AudioManager::ShowAudioInputSettings can potentially launch external + // processes, do that in the PROCESS_LAUNCHER thread to not block the calling + // threads. + if (!BrowserThread::CurrentlyOn(BrowserThread::PROCESS_LAUNCHER)) { + BrowserThread::PostTask( + BrowserThread::PROCESS_LAUNCHER, FROM_HERE, + NewRunnableFunction(&SpeechInputManager::ShowAudioInputSettings)); + return; + } + + DCHECK(AudioManager::GetAudioManager()->CanShowAudioInputSettings()); + if (AudioManager::GetAudioManager()->CanShowAudioInputSettings()) + AudioManager::GetAudioManager()->ShowAudioInputSettings(); +} + SpeechInputManagerImpl::SpeechInputManagerImpl() : recording_caller_id_(0), bubble_controller_(new SpeechInputBubbleController( @@ -340,11 +357,12 @@ void SpeechInputManagerImpl::DidCompleteEnvironmentEstimation(int caller_id) { bubble_controller_->SetBubbleRecordingMode(caller_id); } -void SpeechInputManagerImpl::SetInputVolume(int caller_id, float volume) { +void SpeechInputManagerImpl::SetInputVolume(int caller_id, float volume, + float noise_volume) { DCHECK(HasPendingRequest(caller_id)); DCHECK_EQ(recording_caller_id_, caller_id); - bubble_controller_->SetBubbleInputVolume(caller_id, volume); + bubble_controller_->SetBubbleInputVolume(caller_id, volume, noise_volume); } void SpeechInputManagerImpl::CancelRecognitionAndInformDelegate(int caller_id) { diff --git a/content/browser/speech/endpointer/endpointer.h b/content/browser/speech/endpointer/endpointer.h index be4bd65..c8cf80a 100644 --- a/content/browser/speech/endpointer/endpointer.h +++ b/content/browser/speech/endpointer/endpointer.h @@ -96,6 +96,9 @@ class Endpointer { return speech_input_complete_; } + // RMS background noise level in dB. + float NoiseLevelDb() const { return energy_endpointer_.GetNoiseLevelDb(); } + private: // Reset internal states. Helper method common to initial input utterance // and following input utternaces. diff --git a/content/browser/speech/endpointer/energy_endpointer.cc b/content/browser/speech/endpointer/energy_endpointer.cc index c806aed..edf3edd 100644 --- a/content/browser/speech/endpointer/energy_endpointer.cc +++ b/content/browser/speech/endpointer/energy_endpointer.cc @@ -33,6 +33,13 @@ int64 Secs2Usecs(float seconds) { return static_cast<int64>(0.5 + (1.0e6 * seconds)); } +float GetDecibel(float value) { + const float kVerySmallValue = 1.0e-100f; + if (value < kVerySmallValue) + value = kVerySmallValue; + return 20 * log10(value); +} + } // namespace namespace speech_input { @@ -326,11 +333,12 @@ void EnergyEndpointer::ProcessAudioFrame(int64 time_us, UpdateLevels(rms); ++frame_counter_; - if (rms_out) { - *rms_out = -120.0; - if ((noise_level_ > 0.0) && ((rms / noise_level_ ) > 0.000001)) - *rms_out = static_cast<float>(20.0 * log10(rms / noise_level_)); - } + if (rms_out) + *rms_out = GetDecibel(rms); +} + +float EnergyEndpointer::GetNoiseLevelDb() const { + return GetDecibel(noise_level_); } void EnergyEndpointer::UpdateLevels(float rms) { diff --git a/content/browser/speech/endpointer/energy_endpointer.h b/content/browser/speech/endpointer/energy_endpointer.h index b10d8b7..77ccc55 100644 --- a/content/browser/speech/endpointer/energy_endpointer.h +++ b/content/browser/speech/endpointer/energy_endpointer.h @@ -91,6 +91,9 @@ class EnergyEndpointer { return estimating_environment_; } + // Returns estimated noise level in dB. + float GetNoiseLevelDb() const; + private: class HistoryRing; diff --git a/content/browser/speech/speech_input_manager.h b/content/browser/speech/speech_input_manager.h index a6ba61f..9415910 100644 --- a/content/browser/speech/speech_input_manager.h +++ b/content/browser/speech/speech_input_manager.h @@ -35,6 +35,10 @@ class SpeechInputManager { // information and command line flags. static bool IsFeatureEnabled(); + // Invokes the platform provided microphone settings UI in a non-blocking way, + // via the BrowserThread::PROCESS_LAUNCHER thread. + static void ShowAudioInputSettings(); + // Factory method to access the singleton. We have this method here instead of // using Singleton directly in the calling code to aid tests in injection // mocks. diff --git a/content/browser/speech/speech_recognizer.cc b/content/browser/speech/speech_recognizer.cc index fdc1a4c..b23f4b0 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(); diff --git a/content/browser/speech/speech_recognizer.h b/content/browser/speech/speech_recognizer.h index a54a59d..f8df0c2 100644 --- a/content/browser/speech/speech_recognizer.h +++ b/content/browser/speech/speech_recognizer.h @@ -65,8 +65,9 @@ class SpeechRecognizer // Informs of a change in the captured audio level, useful if displaying // a microphone volume indicator while recording. - // The value of |volume| is in the [0.0, 1.0] range. - virtual void SetInputVolume(int caller_id, float volume) = 0; + // The value of |volume| and |noise_volume| is in the [0.0, 1.0] range. + virtual void SetInputVolume(int caller_id, float volume, + float noise_volume) = 0; protected: virtual ~Delegate() {} diff --git a/content/browser/speech/speech_recognizer_unittest.cc b/content/browser/speech/speech_recognizer_unittest.cc index 8365396..4b16259 100644 --- a/content/browser/speech/speech_recognizer_unittest.cc +++ b/content/browser/speech/speech_recognizer_unittest.cc @@ -62,8 +62,9 @@ class SpeechRecognizerTest : public SpeechRecognizerDelegate, error_ = error; } - virtual void SetInputVolume(int caller_id, float volume) { + virtual void SetInputVolume(int caller_id, float volume, float noise_volume) { volume_ = volume; + noise_volume_ = noise_volume; } // testing::Test methods. @@ -83,6 +84,15 @@ class SpeechRecognizerTest : public SpeechRecognizerDelegate, audio_packet_[i] = static_cast<uint8>(i); } + void FillPacketWithNoise() { + int value = 0; + int factor = 175; + for (size_t i = 0; i < audio_packet_.size(); ++i) { + value += factor; + audio_packet_[i] = value % 100; + } + } + protected: MessageLoopForIO message_loop_; BrowserThread io_thread_; @@ -95,6 +105,7 @@ class SpeechRecognizerTest : public SpeechRecognizerDelegate, TestAudioInputControllerFactory audio_input_controller_factory_; std::vector<uint8> audio_packet_; float volume_; + float noise_volume_; }; TEST_F(SpeechRecognizerTest, StopNoData) { @@ -272,6 +283,7 @@ TEST_F(SpeechRecognizerTest, SetInputVolumeCallback) { // Feed some samples to begin with for the endpointer to do noise estimation. int num_packets = SpeechRecognizer::kEndpointerEstimationTimeMs / SpeechRecognizer::kAudioPacketIntervalMs; + FillPacketWithNoise(); for (int i = 0; i < num_packets; ++i) { controller->event_handler()->OnData(controller, &audio_packet_[0], audio_packet_.size()); @@ -283,13 +295,14 @@ TEST_F(SpeechRecognizerTest, SetInputVolumeCallback) { controller->event_handler()->OnData(controller, &audio_packet_[0], audio_packet_.size()); MessageLoop::current()->RunAllPending(); - EXPECT_EQ(0, volume_); + EXPECT_FLOAT_EQ(0.51877826f, volume_); FillPacketWithTestWaveform(); controller->event_handler()->OnData(controller, &audio_packet_[0], audio_packet_.size()); MessageLoop::current()->RunAllPending(); - EXPECT_FLOAT_EQ(0.9f, volume_); + EXPECT_FLOAT_EQ(0.81907868f, volume_); + EXPECT_FLOAT_EQ(0.52143687f, noise_volume_); EXPECT_EQ(SpeechRecognizer::RECOGNIZER_NO_ERROR, error_); EXPECT_FALSE(recording_complete_); |
