214 lines
7.4 KiB
C#
214 lines
7.4 KiB
C#
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using Microsoft.CognitiveServices.Speech;
|
|
using System.Threading.Tasks;
|
|
using System.IO;
|
|
using System;
|
|
using System.Collections;
|
|
#if PLATFORM_ANDROID
|
|
using UnityEngine.Android;
|
|
using UnityEngine.Networking;
|
|
#endif
|
|
#if PLATFORM_IOS
|
|
using UnityEngine.iOS;
|
|
using System.Collections;
|
|
#endif
|
|
|
|
public class VWU_AzureExample : VoiceWakeUp
|
|
{
|
|
// Hook up the two properties below with a Text and Button object in your UI.
|
|
//public Text outputText;
|
|
//public Button startRecoButton;
|
|
|
|
private object threadLocker = new object();
|
|
private bool waitingForReco;
|
|
private string message;
|
|
|
|
private bool micPermissionGranted = false;
|
|
private string kwsModelDir;
|
|
[SerializeField]
|
|
private string key = "";
|
|
[SerializeField]
|
|
private string ServiceRegion = "eastasia";
|
|
[SerializeField]
|
|
private string kwsModelFile = "kws.table";
|
|
private const string keyword = "hey mike";
|
|
|
|
#if PLATFORM_ANDROID || PLATFORM_IOS
|
|
// Required to manifest microphone permission, cf.
|
|
// https://docs.unity3d.com/Manual/android-manifest.html
|
|
private Microphone mic;
|
|
#endif
|
|
|
|
public async void ButtonClick()
|
|
{
|
|
try
|
|
{
|
|
lock (threadLocker)
|
|
{
|
|
waitingForReco = true;
|
|
}
|
|
// Creates an instance of a speech config with specified subscription key and service region.
|
|
// Replace with your own subscription key and service region (e.g., "westus").
|
|
var config = SpeechConfig.FromSubscription(key, ServiceRegion);
|
|
|
|
#if PLATFORM_ANDROID
|
|
kwsModelDir = Application.persistentDataPath + Path.DirectorySeparatorChar + kwsModelFile;
|
|
#else
|
|
kwsModelDir = Application.streamingAssetsPath + Path.DirectorySeparatorChar + kwsModelFile;
|
|
#endif
|
|
UnityEngine.Debug.Log(kwsModelDir);
|
|
var model = KeywordRecognitionModel.FromFile(kwsModelDir);
|
|
|
|
var stopRecognition = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
var resultStr = "";
|
|
|
|
// Creates a speech recognizer using microphone as audio input.
|
|
using (var recognizer = new SpeechRecognizer(config))
|
|
{
|
|
// Subscribes to events.
|
|
recognizer.Recognized += (s, e) =>
|
|
{
|
|
if (e.Result.Reason == ResultReason.RecognizedKeyword)
|
|
{
|
|
resultStr = $"RECOGNIZED KEYWORD: '{e.Result.Text}'";
|
|
}
|
|
else if (e.Result.Reason == ResultReason.RecognizedSpeech)
|
|
{
|
|
resultStr = $"RECOGNIZED: '{e.Result.Text}'";
|
|
}
|
|
else if (e.Result.Reason == ResultReason.NoMatch)
|
|
{
|
|
resultStr = "NOMATCH: Speech could not be recognized.";
|
|
}
|
|
UnityEngine.Debug.Log(resultStr);
|
|
lock (threadLocker)
|
|
{
|
|
message = resultStr;
|
|
}
|
|
};
|
|
|
|
recognizer.Canceled += (s, e) =>
|
|
{
|
|
var cancellation = CancellationDetails.FromResult(e.Result);
|
|
resultStr = $"CANCELED: Reason={cancellation.Reason} ErrorDetails={cancellation.ErrorDetails}";
|
|
if (cancellation.Reason == CancellationReason.Error)
|
|
{
|
|
lock (threadLocker)
|
|
{
|
|
message = resultStr;
|
|
}
|
|
}
|
|
UnityEngine.Debug.Log(resultStr);
|
|
stopRecognition.TrySetResult(0);
|
|
};
|
|
|
|
recognizer.SessionStarted += (s, e) =>
|
|
{
|
|
UnityEngine.Debug.Log("\nSession started event.");
|
|
};
|
|
|
|
recognizer.SessionStopped += (s, e) =>
|
|
{
|
|
UnityEngine.Debug.Log("\nSession stopped event.");
|
|
UnityEngine.Debug.Log("\nStop recognition.");
|
|
stopRecognition.TrySetResult(0);
|
|
};
|
|
|
|
UnityEngine.Debug.Log($"Say something starting with the keyword '{keyword}' followed by whatever you want...");
|
|
|
|
// Starts continuous recognition using the keyword model. Use StopKeywordRecognitionAsync() to stop recognition.
|
|
await recognizer.StartKeywordRecognitionAsync(model).ConfigureAwait(false);
|
|
|
|
// Waits for a single successful keyword-triggered speech recognition (or error).
|
|
// Use Task.WaitAny to keep the task rooted.
|
|
Task.WaitAny(new[] { stopRecognition.Task });
|
|
|
|
await recognizer.StopKeywordRecognitionAsync().ConfigureAwait(false);
|
|
|
|
lock (threadLocker)
|
|
{
|
|
waitingForReco = false;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
lock (threadLocker)
|
|
{
|
|
message = "Exception: " + ex.ToString();
|
|
waitingForReco = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if PLATFORM_ANDROID
|
|
IEnumerator CopyKwsModelFileFromStreamingAssetsAsync()
|
|
{
|
|
string fromFile = Application.streamingAssetsPath + Path.DirectorySeparatorChar + kwsModelFile;
|
|
string toFile = Application.persistentDataPath + Path.DirectorySeparatorChar + kwsModelFile;
|
|
|
|
UnityWebRequest downloader = UnityWebRequest.Get(fromFile);
|
|
yield return downloader.SendWebRequest();
|
|
DownloadHandler handler = downloader.downloadHandler;
|
|
File.WriteAllBytes(toFile, handler.data);
|
|
}
|
|
#endif
|
|
|
|
void Start()
|
|
{
|
|
Debug.Log("Start enter");
|
|
|
|
// Continue with normal initialization, Text and Button objects are present.
|
|
#if PLATFORM_ANDROID
|
|
// Request to use the microphone, cf.
|
|
// https://docs.unity3d.com/Manual/android-RequestingPermissions.html
|
|
message = "Waiting for mic permission";
|
|
if (!Permission.HasUserAuthorizedPermission(Permission.Microphone))
|
|
{
|
|
Permission.RequestUserPermission(Permission.Microphone);
|
|
}
|
|
StartCoroutine(CopyKwsModelFileFromStreamingAssetsAsync());
|
|
|
|
#elif PLATFORM_IOS
|
|
if (!Application.HasUserAuthorization(UserAuthorization.Microphone))
|
|
{
|
|
Application.RequestUserAuthorization(UserAuthorization.Microphone);
|
|
}
|
|
#else
|
|
micPermissionGranted = true;
|
|
message = "Click button to recognize speech using a keyword";
|
|
#endif
|
|
Debug.Log("Start exit");
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
#if PLATFORM_ANDROID
|
|
if (!micPermissionGranted && Permission.HasUserAuthorizedPermission(Permission.Microphone))
|
|
{
|
|
micPermissionGranted = true;
|
|
message = "Click button to recognize speech";
|
|
}
|
|
#elif PLATFORM_IOS
|
|
if (!micPermissionGranted && Application.HasUserAuthorization(UserAuthorization.Microphone))
|
|
{
|
|
micPermissionGranted = true;
|
|
message = "Click button to recognize speech";
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
public override void StartRecgnition(Action<bool> callback)
|
|
{
|
|
base.StartRecgnition(callback);
|
|
ButtonClick();
|
|
}
|
|
|
|
public override void StopRecognition()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|