var speechEngine = null; var speechSession; var mobileCallbacks; var isMobileSreInitialized = false; var configureProgress = 0; var calibrateEnergy = 0; var lfpResponse = null; var lfpScore = -1; var calibrationResult = null; var stopReason = null; var errorMessage = null; var isIosSessionRunning = false; sonic_wrapper = { /** * SREロード * * @param {Function} callbacks SREロードイベントコールバック * @param {Boolean} forceFlash Flash実行フラグ */ loadSonic: function (callbacks, forceFlash) { $(sonic_loader) .off("error") .off("progress") .off("ready") .on("error", function (event, message) { if (callbacks && callbacks.error) { callbacks.error(message); } }) .on("progress", function (event, progress) { if (callbacks && callbacks.progress) { callbacks.progress(progress); } }) .on("ready", function () { if (callbacks && callbacks.ready) { callbacks.ready(); } }); var params; if (forceFlash) { params = { html5UrlPath: "static/sonic/html5/", flashUrlPath: "static/sonic/flash/", forceHTML5: false, forceFlash: forceFlash }; } else { params = { html5UrlPath: "static/sonic/html5/", flashUrlPath: "static/sonic/flash/" }; } sonic_loader.load(params); }, /** * SpeechEngine初期化 * * @param {String} language 言語 * @param {String} gender 性別 * @param {Number} difficulty 難易度 * @param {Number} needsLog ログ出力要否 * @param {Boolean} forceFlash Flash実行フラグ */ initEngine: function (language, gender, difficulty, needsLog, forceFlash) { var self = this; return new Promise(function (resolve, reject) { var state = false; var sessionCallbacks = { success: function () { state = true; }, error: function () { state = false; }, end: function () { if (state) { resolve(); } else { reject(self.getErrorMessage()); } } }; if (window.hasOwnProperty('Phone')) { var loadCallbacks = { error: function () { isMobileSreInitialized = false; reject("Error initialize SRE"); }, ready: function () { isMobileSreInitialized = true; self.loadSpeechModel(language, gender, difficulty, sessionCallbacks); } } mobileCallbacks = loadCallbacks; window.Phone.InitSre(); } else { var loadCallbacks = { error: function (message) { reject("Error loading sonic SRE: " + message); }, ready: function () { if (!sonic.isInitialized) { var message = ""; if (swfobject.hasFlashPlayerVersion("1")) { var flashPlayerVersion = swfobject.getFlashPlayerVersion(); message = "You have FlashPlayer " + flashPlayerVersion.major + "." + flashPlayerVersion.minor; } else { message = "You don't have FlashPlayer installed"; } reject("Unable to initialize sonic. " + message + "; FlashPlayer " + sonic.flashPlayerMinVersion + "+ is required. If the minimum requirement has been met, there may be permissions problems."); } else { speechEngine = sonic.createPlatformSpeechEngine(); // This method disables the ability to upload soundlogs to our CouchDB SRE repository, used // for troubleshooting and further analysis speechEngine.setSaveSoundLogToWeb(false); if (!needsLog) { speechEngine.setLogLevel(sonic.globals.getLEVEL_SILENT()); } self.loadSpeechModel(language, gender, difficulty, sessionCallbacks); } } }; self.loadSonic(loadCallbacks, forceFlash); } }); }, /** * LoadModelSession実行 * * @param {String} language 言語 * @param {String} gender 性別 * @param {Number} difficulty 難易度 * @param {Function} callbacks セッションイベントコールバック */ loadSpeechModel: function (language, gender, difficulty, callbacks) { if (window.hasOwnProperty('Phone')) { mobileCallbacks = callbacks; window.Phone.LoadModelSession(language, gender, difficulty == 0 ? 1 : difficulty); } else { speechEngine.getSpeechModelProvider().setIdentifier("Callisto"); speechSession = speechEngine.createLoadModelSession({ language: language, voiceType: gender }, difficulty); this.executeSession(callbacks); } }, /** * CalibrateSession実行 * * @param {Function} callbacks セッションイベントコールバック */ calibration: function (callbacks) { if (window.hasOwnProperty('Phone')) { mobileCallbacks = callbacks; window.Phone.CalibrateSession(); } else { speechSession = speechEngine.createCalibrateSession(); speechSession.withDefaultPromptSound(); speechSession.withMetadata(sonic.globals.getAUDIO_METADATA_ENERGY()); this.executeSession(callbacks); } }, /** * ListenForPhrasesSession実行 * * @param {Array} phrases 認識するフレーズ(string配列) * @param {Function} callbacks セッションイベントコールバック */ listenForPhrases: function (phrases, callbacks) { if (window.hasOwnProperty('Phone')) { mobileCallbacks = callbacks; window.Phone.ListenForPhrasesSession(phrases); } else { speechSession = speechEngine.createListenForPhrasesSession(phrases); speechSession.withDefaultPromptSound(); this.executeSession(callbacks); } }, /** * 実行中セッションの中断 */ interruptSession: function () { if (!this.isSessionRunning()) { return; } stopReason = this.getStopReason("STOP_REASON_MANUAL"); if (window.hasOwnProperty('Phone')) { window.Phone.InterruptSession(); } else { speechSession.interrupt(); } }, /** * セッション実行 * * @param {Function} callbacks セッションイベントコールバック */ executeSession: function (callbacks) { $(speechSession) .on("start", null, function () { if (callbacks && callbacks.start) { callbacks.start(); } }) .on("update", null, function () { if (callbacks && callbacks.update) { callbacks.update(); } }) .on("interrupting", null, function () { if (callbacks && callbacks.interrupting) { callbacks.interrupting(); } }) .on("success", null, function () { if (callbacks && callbacks.success) { callbacks.success(); } }) .on("error", null, function () { if (callbacks && callbacks.error) { callbacks.error(); } }) .on("end", null, function () { if (stopReason != sonic.globals.getSTOP_REASON_MANUAL()) { stopReason = (typeof speechSession.getStopReason == "function") ? speechSession.getStopReason() : null; } if (callbacks && callbacks.end) { callbacks.end(); } speechSession = null; }); stopReason = sonic.globals.getSTOP_REASON_AUTO(); speechSession.run(); }, /** * 使用マイクを設定する * * @param {Object} microphone マイクオブジェクト */ setUseMicrophone: function (microphone) { var deviceId = microphone && microphone.id ? microphone.id : microphone; speechEngine.getAudioEnumerator().openInputDevice(deviceId); speechEngine.setMicrophone(microphone ? microphone : ""); }, /** * SRE初期化済みか否かを返す * * @return {Boolean} true:初期化済, false:未初期化 */ isSreInitialized: function () { if (window.hasOwnProperty('Phone')) { return isMobileSreInitialized; } else { return speechEngine != null; } }, /** * SREに設定されているマイクオブジェクトを取得する * * @return {Object} マイクオブジェクト */ getMicrophone: function () { if (window.hasOwnProperty('Phone')) { return null; } else { return speechEngine.getMicrophone(); } }, /** * アクティブなセッションがあるかどうか * * @return {Boolean} true:セッションあり, false:セッションなし */ isSessionRunning: function () { if (window.hasOwnProperty('Phone')) { var mobilePlatformName = window.Phone.GetPlatformName(); switch (mobilePlatformName) { case "android": return window.Phone.IsSessionRunning() == "1"; case "ios": return isIosSessionRunning; default: return false; } } else { return speechSession != null; } }, /** * CalibrateSessionの音声ボリューム値を返す * * @return {Number} 音声ボリューム値 */ getCalibrateEnergy: function () { var energy = window.hasOwnProperty('Phone') ? calibrateEnergy : speechSession ? speechSession.getMeanFrameEnergy() : 0; return energy * 10; }, /** * ListenForPhrasesSessionの発話結果情報有無を返す * * @return {Boolean} true:発話結果情報有り, false:発話結果情報無し */ hasLfpHypothesisResponse: function () { if (window.hasOwnProperty('Phone')) { return lfpResponse != null; } else { return speechSession && speechSession.hasHypothesis(); } }, /** * ListenForPhrasesSessionの推測発話文字列を返す * * @return {String} 推測発話文字列 */ getLfpResponse: function () { if (window.hasOwnProperty('Phone')) { return lfpResponse; } else { return this.hasLfpHypothesisResponse() ? speechSession.getHypothesis().getResponse() : null; } }, /** * ListenForPhrasesSessionの発話結果情報有無を返す * * @return {Boolean} true:発話結果情報有り, false:発話結果情報無し */ hasLfpHypothesisScore: function () { if (window.hasOwnProperty('Phone')) { return 0 <= lfpScore; } else { return speechSession && speechSession.hasHypothesis(); } }, /** * ListenForPhrasesSessionの音声認識結果スコアを返す * * @return {Number} スコア */ getLfpScore: function () { if (window.hasOwnProperty('Phone')) { return lfpScore; } else { return this.hasLfpHypothesisScore() ? speechSession.getHypothesis().getGrading().getScore() : -1; } }, /** * セッション実行エラー時のエラーメッセージを返す * * @return {String} エラーメッセージ */ getErrorMessage: function () { if (window.hasOwnProperty('Phone')) { return errorMessage; } else { return speechSession ? speechSession.getErrorMessage() : null; } }, /** * セッションのStopReasonがSTOP_REASON_MANUALか否かを返す * * @return {Boolean} true:StopReasonがSTOP_REASON_MANUAL, false:左記以外 */ isStopReasonManual: function () { return stopReason == this.getStopReason("STOP_REASON_MANUAL"); }, /** * セッションのCalibrationResultがCALIBRATION_RESULT_OKか否かを返す * * @return {Boolean} true:CalibrationResultがCALIBRATION_RESULT_OK, false:左記以外 */ isCalibrationResultOk: function () { var ok = this.getCalibrationResult("CALIBRATION_RESULT_OK"); if (window.hasOwnProperty('Phone')) { return calibrationResult == ok; } else { return speechSession.getAudioQuality().getCalibration_result() == ok; } }, /** * CalibrationResultを取得する * * @param {String} constantName 定数名 * @return {Object} CalibrationResult */ getCalibrationResult: function (constantName) { if (window.hasOwnProperty('Phone')) { var mobilePlatformName = window.Phone.GetPlatformName(); switch (mobilePlatformName) { case "android": return window.Phone.GetCalibrationResult(constantName); case "ios": return this.getIosCalibrationResult(constantName); default: return null; } } else { return this.getPcCalibrationResult(constantName); } }, /** * PC版のCalibrationResultを取得する * * @param {String} constantName 定数名 * @return {Object} CalibrationResult */ getPcCalibrationResult: function (constantName) { switch (constantName) { case "CALIBRATION_RESULT_OK": return sonic.globals.getCALIBRATION_RESULT_OK(); case "CALIBRATION_RESULT_TOO_LOUD": return sonic.globals.getCALIBRATION_RESULT_TOO_LOUD(); case "CALIBRATION_RESULT_TOO_SOFT": return sonic.globals.getCALIBRATION_RESULT_TOO_SOFT(); case "CALIBRATION_RESULT_NO_SIGNAL": return sonic.globals.getCALIBRATION_RESULT_NO_SIGNAL(); default: return null; } }, /** * iOS版のCalibrationResultを取得する * * @param {String} constantName 定数名 * @return {Object} CalibrationResult */ getIosCalibrationResult: function (constantName) { // iOS用SREライブラリのSREEnums.hで定義されているEnum値と同等の値を返す switch (constantName) { case "CALIBRATION_RESULT_OK": return "0"; case "CALIBRATION_RESULT_TOO_LOUD": return "1"; case "CALIBRATION_RESULT_TOO_SOFT": return "2"; case "CALIBRATION_RESULT_NO_SIGNAL": return "3"; default: return null; } }, /** * StopReasonを取得する * * @param {String} constantName 定数名 * @return {Object} StopReason */ getStopReason: function (constantName) { if (window.hasOwnProperty('Phone')) { var mobilePlatformName = window.Phone.GetPlatformName(); switch (mobilePlatformName) { case "android": return window.Phone.GetStopReason(constantName); case "ios": return this.getIosStopReason(constantName); default: return null; } } else { return this.getPcStopReason(constantName); } }, /** * PC版のStopReasonを取得する * * @param {String} constantName 定数名 * @return {Object} StopReason */ getPcStopReason: function (constantName) { switch (constantName) { case "STOP_REASON_NONE": return sonic.globals.getSTOP_REASON_NONE(); case "STOP_REASON_MANUAL": return sonic.globals.getSTOP_REASON_MANUAL(); case "STOP_REASON_AUTO": return sonic.globals.getSTOP_REASON_AUTO(); case "STOP_REASON_SILENCE_TIMEOUT": return sonic.globals.getSTOP_REASON_SILENCE_TIMEOUT(); case "STOP_REASON_DURATION_TIMEOUT": return sonic.globals.getSTOP_REASON_DURATION_TIMEOUT(); default: return null; } }, /** * iOS版のStopReasonを取得する * * @param {String} constantName 定数名 * @return {Object} StopReason */ getIosStopReason: function (constantName) { // iOS用SREライブラリのSREEnums.hで定義されているEnum値と同等の値を返す switch (constantName) { case "STOP_REASON_NONE": return "0"; case "STOP_REASON_MANUAL": return "1"; case "STOP_REASON_AUTO": return "2"; case "STOP_REASON_SILENCE_TIMEOUT": return "3"; case "STOP_REASON_DURATION_TIMEOUT": return "4"; default: return null; } } }; /** * モバイルアプリ版初期処理成功コールバック */ function ROSETTA_SRE_onUse () { if (mobileCallbacks && mobileCallbacks.ready) { mobileCallbacks.ready(); } }; /** * モバイルアプリ版初期処理失敗コールバック */ function ROSETTA_SRE_onNotUse () { if (mobileCallbacks && mobileCallbacks.error) { mobileCallbacks.error(); } }; /** * モバイルアプリ版Startイベントコールバック共通処理 */ function initOnStart () { isIosSessionRunning = true; configureProgress = 0; calibrateEnergy = 0; lfpResponse = null; lfpScore = -1; calibrationResult = sonic_wrapper.getCalibrationResult("CALIBRATION_RESULT_OK"); stopReason = sonic_wrapper.getStopReason("STOP_REASON_AUTO"); errorMessage = null; if (mobileCallbacks && mobileCallbacks.start) { mobileCallbacks.start(); } }; /** * モバイルアプリ版LoadModelSessionのStartイベントコールバック */ function ROSETTA_SRE_onConfigureStart () { initOnStart(); }; /** * モバイルアプリ版LoadModelSessionのUpdateイベントコールバック * * @param {String} progress 進捗率 */ function ROSETTA_SRE_onConfigureUpdate (progress) { configureProgress = Number(progress); if (mobileCallbacks && mobileCallbacks.update) { mobileCallbacks.update(); } }; /** * モバイルアプリ版LoadModelSessionのCompleteイベントコールバック */ function ROSETTA_SRE_onConfigureComplete () { isIosSessionRunning = false; configureProgress = 0; if (mobileCallbacks) { if (mobileCallbacks.success) { mobileCallbacks.success(); } if (mobileCallbacks.end) { mobileCallbacks.end(); } mobileCallbacks = null; } }; /** * モバイルアプリ版LoadModelSessionのErrorイベントコールバック * * @param {String} errorCode エラーコード */ function ROSETTA_SRE_onConfigureError (errorCode) { isIosSessionRunning = false; configureProgress = 0; errorMessage = "SRE ERROR(" + errorCode + ")"; if (mobileCallbacks) { if (mobileCallbacks.error) { mobileCallbacks.error(); } if (mobileCallbacks.end) { mobileCallbacks.end(); } mobileCallbacks = null; } }; /** * モバイルアプリ版CalibrateSessionのStartイベントコールバック */ function ROSETTA_SRE_onCalibrateStart () { initOnStart(); }; /** * モバイルアプリ版CalibrateSessionのUpdateイベントコールバック * * @param {String} energy 音声ボリューム値 */ function ROSETTA_SRE_onCalibrateUpdate (energy) { calibrateEnergy = Number(energy); if (mobileCallbacks && mobileCallbacks.update) { mobileCallbacks.update(); } }; /** * モバイルアプリ版CalibrateSessionのCompleteイベントコールバック * * @param {String} result CalibrationResult */ function ROSETTA_SRE_onCalibrateComplete (result) { isIosSessionRunning = false; calibrateEnergy = 0; calibrationResult = result; if (mobileCallbacks) { if (mobileCallbacks.success) { mobileCallbacks.success(); } if (mobileCallbacks.end) { mobileCallbacks.end(); } mobileCallbacks = null; } }; /** * モバイルアプリ版CalibrateSessionのErrorイベントコールバック * * @param {String} errorCode エラーコード */ function ROSETTA_SRE_onCalibrateError (errorCode) { isIosSessionRunning = false; calibrateEnergy = 0; calibrationResult = sonic_wrapper.getCalibrationResult("CALIBRATION_RESULT_NO_SIGNAL"); if (stopReason != sonic_wrapper.getStopReason("STOP_REASON_MANUAL")) { stopReason = sonic_wrapper.getStopReason("STOP_REASON_NONE"); } errorMessage = "SRE ERROR(" + errorCode + ")"; if (mobileCallbacks) { if (mobileCallbacks.error) { mobileCallbacks.error(); } if (mobileCallbacks.end) { mobileCallbacks.end(); } mobileCallbacks = null; } }; /** * モバイルアプリ版ListenForPhrasesSessionのStartイベントコールバック */ function ROSETTA_SRE_onLFPStart () { initOnStart(); }; /** * モバイルアプリ版ListenForPhrasesSessionのUpdateイベントコールバック * * @param {String} energy 音声ボリューム値 * @param {String} response 推測発話文字列 */ function ROSETTA_SRE_onLFPUpdate (energy, response) { lfpResponse = response; if (mobileCallbacks && mobileCallbacks.update) { mobileCallbacks.update(); } }; /** * モバイルアプリ版CalibrateSessionのCompleteイベントコールバック * * @param {String} score スコア * @param {String} reason StopReason */ function ROSETTA_SRE_onLFPComplete (score, reason) { isIosSessionRunning = false; if (reason == sonic_wrapper.getStopReason("STOP_REASON_SILENCE_TIMEOUT")) { if(Number(score) == 0) { calibrationResult = sonic_wrapper.getCalibrationResult("CALIBRATION_RESULT_NO_SIGNAL"); } else { calibrationResult = sonic_wrapper.getCalibrationResult("CALIBRATION_RESULT_OK"); } } else { calibrationResult = sonic_wrapper.getCalibrationResult("CALIBRATION_RESULT_OK"); } if (stopReason != sonic_wrapper.getStopReason("STOP_REASON_MANUAL")) { stopReason = reason; } lfpResponse = null; lfpScore = Number(score); if (mobileCallbacks) { if (mobileCallbacks.success) { mobileCallbacks.success(); } if (mobileCallbacks.end) { mobileCallbacks.end(); } mobileCallbacks = null; } }; /** * モバイルアプリ版CalibrateSessionのErrorイベントコールバック * * @param {String} errorCode エラーコード */ function ROSETTA_SRE_onLFPError (errorCode) { isIosSessionRunning = false; calibrationResult = sonic_wrapper.getCalibrationResult("CALIBRATION_RESULT_NO_SIGNAL"); if (stopReason != sonic_wrapper.getStopReason("STOP_REASON_MANUAL")) { stopReason = sonic_wrapper.getStopReason("STOP_REASON_NONE"); } lfpResponse = null; lfpScore = -1; errorMessage = "SRE ERROR(" + errorCode + ")"; if (mobileCallbacks) { if (mobileCallbacks.error) { mobileCallbacks.error(); } if (mobileCallbacks.end) { mobileCallbacks.end(); } mobileCallbacks = null; } }; /** * モバイルアプリ版:端末電源ON時の開始コールバック */ function ROSETTA_SRE_onStart () {}; /** * モバイルアプリ版:端末電源OFF時の停止コールバック */ function ROSETTA_SRE_onStop () {};