| // Copyright 2017 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "cobalt/speech/starboard_speech_recognizer.h" |
| |
| #if defined(SB_USE_SB_SPEECH_RECOGNIZER) |
| |
| #include "cobalt/base/tokens.h" |
| #include "cobalt/speech/speech_recognition_error.h" |
| #include "cobalt/speech/speech_recognition_event.h" |
| #include "starboard/log.h" |
| |
| namespace cobalt { |
| namespace speech { |
| |
| namespace { |
| |
| using cobalt::speech::StarboardSpeechRecognizer; |
| |
| void OnSpeechDetected(void* context, bool detected) { |
| StarboardSpeechRecognizer* recognizer = |
| static_cast<StarboardSpeechRecognizer*>(context); |
| recognizer->OnRecognizerSpeechDetected(detected); |
| } |
| |
| void OnError(void* context, SbSpeechRecognizerError error) { |
| StarboardSpeechRecognizer* recognizer = |
| static_cast<StarboardSpeechRecognizer*>(context); |
| recognizer->OnRecognizerError(error); |
| } |
| |
| void OnResults(void* context, SbSpeechResult* results, int results_size, |
| bool is_final) { |
| StarboardSpeechRecognizer* recognizer = |
| static_cast<StarboardSpeechRecognizer*>(context); |
| recognizer->OnRecognizerResults(results, results_size, is_final); |
| } |
| |
| } // namespace |
| |
| StarboardSpeechRecognizer::StarboardSpeechRecognizer( |
| const EventCallback& event_callback) |
| : SpeechRecognizer(event_callback) { |
| SbSpeechRecognizerHandler handler = {&OnSpeechDetected, &OnError, &OnResults, |
| this}; |
| speech_recognizer_ = SbSpeechRecognizerCreate(&handler); |
| |
| if (!SbSpeechRecognizerIsValid(speech_recognizer_)) { |
| scoped_refptr<dom::Event> error_event(new SpeechRecognitionError( |
| kSpeechRecognitionErrorCodeServiceNotAllowed, "")); |
| RunEventCallback(error_event); |
| } |
| } |
| |
| StarboardSpeechRecognizer::~StarboardSpeechRecognizer() { |
| if (SbSpeechRecognizerIsValid(speech_recognizer_)) { |
| SbSpeechRecognizerDestroy(speech_recognizer_); |
| } |
| } |
| |
| void StarboardSpeechRecognizer::Start(const SpeechRecognitionConfig& config) { |
| SbSpeechConfiguration configuration = { |
| config.continuous, config.interim_results, config.max_alternatives}; |
| if (SbSpeechRecognizerIsValid(speech_recognizer_)) { |
| SbSpeechRecognizerStart(speech_recognizer_, &configuration); |
| } |
| } |
| |
| void StarboardSpeechRecognizer::Stop() { |
| if (SbSpeechRecognizerIsValid(speech_recognizer_)) { |
| SbSpeechRecognizerStop(speech_recognizer_); |
| } |
| // Clear the final results. |
| final_results_.clear(); |
| } |
| |
| void StarboardSpeechRecognizer::OnRecognizerSpeechDetected(bool detected) { |
| scoped_refptr<dom::Event> event(new dom::Event( |
| detected ? base::Tokens::soundstart() : base::Tokens::soundend())); |
| RunEventCallback(event); |
| } |
| |
| void StarboardSpeechRecognizer::OnRecognizerError( |
| SbSpeechRecognizerError error) { |
| scoped_refptr<dom::Event> error_event; |
| switch (error) { |
| case kSbNoSpeechError: |
| error_event = |
| new SpeechRecognitionError(kSpeechRecognitionErrorCodeNoSpeech, ""); |
| break; |
| case kSbAborted: |
| error_event = |
| new SpeechRecognitionError(kSpeechRecognitionErrorCodeAborted, ""); |
| break; |
| case kSbAudioCaptureError: |
| error_event = new SpeechRecognitionError( |
| kSpeechRecognitionErrorCodeAudioCapture, ""); |
| break; |
| case kSbNetworkError: |
| error_event = |
| new SpeechRecognitionError(kSpeechRecognitionErrorCodeNetwork, ""); |
| break; |
| case kSbNotAllowed: |
| error_event = |
| new SpeechRecognitionError(kSpeechRecognitionErrorCodeNotAllowed, ""); |
| break; |
| case kSbServiceNotAllowed: |
| error_event = new SpeechRecognitionError( |
| kSpeechRecognitionErrorCodeServiceNotAllowed, ""); |
| break; |
| case kSbBadGrammar: |
| error_event = |
| new SpeechRecognitionError(kSpeechRecognitionErrorCodeBadGrammar, ""); |
| break; |
| case kSbLanguageNotSupported: |
| error_event = new SpeechRecognitionError( |
| kSpeechRecognitionErrorCodeLanguageNotSupported, ""); |
| break; |
| } |
| SB_DCHECK(error_event); |
| RunEventCallback(error_event); |
| } |
| |
| void StarboardSpeechRecognizer::OnRecognizerResults(SbSpeechResult* results, |
| int results_size, |
| bool is_final) { |
| SpeechRecognitionResultList::SpeechRecognitionResults recognition_results; |
| SpeechRecognitionResult::SpeechRecognitionAlternatives alternatives; |
| for (int i = 0; i < results_size; ++i) { |
| scoped_refptr<SpeechRecognitionAlternative> alternative( |
| new SpeechRecognitionAlternative(results[i].transcript, |
| results[i].confidence)); |
| alternatives.push_back(alternative); |
| // Platform implementation allocates memory of |transcript|. |
| SbMemoryDeallocate(results[i].transcript); |
| } |
| scoped_refptr<SpeechRecognitionResult> recognition_result( |
| new SpeechRecognitionResult(alternatives, is_final)); |
| recognition_results.push_back(recognition_result); |
| |
| // Gather all results for the SpeechRecognitionEvent, including all final |
| // results we've previously accumulated, plus all (final or not) results that |
| // we just received. |
| SpeechRecognitionResults success_results; |
| size_t total_size = final_results_.size() + recognition_results.size(); |
| success_results.reserve(total_size); |
| success_results = final_results_; |
| success_results.insert(success_results.end(), recognition_results.begin(), |
| recognition_results.end()); |
| |
| size_t result_index = final_results_.size(); |
| // Update final results list with final results that we just received, so we |
| // have them for the next event. |
| for (size_t i = 0; i < recognition_results.size(); ++i) { |
| if (recognition_results[i]->is_final()) { |
| final_results_.push_back(recognition_results[i]); |
| } |
| } |
| |
| scoped_refptr<SpeechRecognitionResultList> recognition_list( |
| new SpeechRecognitionResultList(success_results)); |
| scoped_refptr<SpeechRecognitionEvent> recognition_event( |
| new SpeechRecognitionEvent(SpeechRecognitionEvent::kResult, |
| static_cast<uint32>(result_index), |
| recognition_list)); |
| RunEventCallback(recognition_event); |
| } |
| |
| } // namespace speech |
| } // namespace cobalt |
| |
| #endif // defined(SB_USE_SB_SPEECH_RECOGNIZER) |