1
0
mirror of https://github.com/Picovoice/porcupine.git synced 2022-01-28 03:27:53 +03:00
Files
Alireza Kenarsari 556630dcf4 v2.0
2021-11-25 10:08:21 -08:00

167 lines
7.9 KiB
C#

//
// Copyright 2021 Picovoice Inc.
//
// You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
// file accompanying this source.
//
// 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.
//
using System.Collections.Generic;
using System;
using UnityEngine;
namespace Pv.Unity {
public class PorcupineManager
{
private VoiceProcessor _voiceProcessor;
private Porcupine _porcupine;
private Action<int> _wakeWordCallback;
private Action<PorcupineException> _processErrorCallback;
/// <summary>
/// Creates an instance of the Porcupine wake word engine from built-in keywords
/// </summary>
/// <param name="accessKey">AccessKey obtained from Picovoice Console (https://picovoice.ai/console/)</param>
/// <param name="keywords">
/// List of built-in keywords (phrases) to detect. The list of available (default) keywords can be retrieved
/// using `PorcupineManager.BUILT_IN_KEYWORDS`.
/// </param>
/// <param name="wakeWordCallback">A callback that is triggered when one of the given keywords has been detected by Porcupine.</param>
/// <param name="modelPath">(Optional) Absolute path to the file containing model parameters. If not set it will be set to the default location.</param>
/// <param name="sensitivities">
/// (Optional) Sensitivities for detecting keywords. Each value should be a number within [0, 1]. A higher sensitivity results in fewer
/// misses at the cost of increasing the false alarm rate. If not set 0.5 will be used.
/// </param>
/// <param name="processErrorCallback">(Optional) Callback that triggers is the engine experiences a problem while processing audio.</param>
/// <returns>An instance of PorcupineManager.</returns>
public static PorcupineManager FromBuiltInKeywords(string accessKey, IEnumerable<Porcupine.BuiltInKeyword> keywords, Action<int> wakeWordCallback,
string modelPath = null, IEnumerable<float> sensitivities = null, Action<PorcupineException> processErrorCallback = null)
{
Porcupine porcupine = Porcupine.FromBuiltInKeywords(accessKey: accessKey, keywords: keywords, modelPath: modelPath, sensitivities: sensitivities);
return new PorcupineManager(porcupine, wakeWordCallback, processErrorCallback);
}
/// <summary>
/// Creates an instance of the Porcupine wake word engine from custom keyword files.
/// </summary>
/// <param name="accessKey">AccessKey obtained from Picovoice Console (https://picovoice.ai/console/)</param>
/// <param name="keywordPaths">List of absolute paths to keyword model files (.ppn).</param>
/// <param name="wakeWordCallback">A callback that is triggered when one of the given keywords has been detected by Porcupine.</param>
/// <param name="modelPath">(Optional) Absolute path to the file containing model parameters. If not set it will be set to the default location.</param>
/// <param name="sensitivities">
/// (Optional) Sensitivities for detecting keywords. Each value should be a number within [0, 1]. A higher sensitivity results in fewer
/// misses at the cost of increasing the false alarm rate. If not set 0.5 will be used.
/// </param>
/// <param name="processErrorCallback">(Optional) Callback that triggers is the engine experiences a problem while processing audio.</param>
/// <returns>An instance of PorcupineManager.</returns>
public static PorcupineManager FromKeywordPaths(string accessKey, IEnumerable<string> keywordPaths, Action<int> wakeWordCallback,
string modelPath = null, IEnumerable<float> sensitivities = null, Action<PorcupineException> processErrorCallback = null)
{
Porcupine porcupine = Porcupine.FromKeywordPaths(accessKey: accessKey, keywordPaths: keywordPaths, modelPath: modelPath, sensitivities: sensitivities);
return new PorcupineManager(porcupine, wakeWordCallback, processErrorCallback);
}
// private constructor
private PorcupineManager(Porcupine porcupine, Action<int> wakeWordCallback, Action<PorcupineException> processErrorCallback = null)
{
_porcupine = porcupine;
_wakeWordCallback = wakeWordCallback;
_processErrorCallback = processErrorCallback;
_voiceProcessor = VoiceProcessor.Instance;
_voiceProcessor.OnFrameCaptured += OnFrameCaptured;
}
/// <summary>
/// Action to catch audio frames as voice processor produces them
/// </summary>
/// <param name="pcm">Frame of pcm audio</param>
private void OnFrameCaptured(short[] pcm)
{
try
{
int keywordIndex = _porcupine.Process(pcm);
if (keywordIndex >= 0)
{
if (_wakeWordCallback != null)
_wakeWordCallback.Invoke(keywordIndex);
}
}
catch (Exception ex)
{
if (_processErrorCallback != null)
_processErrorCallback(new PorcupineException(ex.Message));
else
Debug.LogError(ex.ToString());
}
}
/// <summary>
/// Checks to see whether PorcupineManager is capturing audio or not
/// </summary>
/// <returns>whether PorcupineManager is capturing audio or not</returns>
public bool IsRecording => _voiceProcessor.IsRecording;
/// <summary>
/// Checks to see whether there are any audio capture devices available
/// </summary>
/// <returns>whether there are any audio capture devices available</returns>
public bool IsAudioDeviceAvailable()
{
_voiceProcessor.UpdateDevices();
return _voiceProcessor.CurrentDeviceIndex >= 0;
}
/// <summary>
/// Starts audio capture and wake word detection
/// </summary>
public void Start()
{
if (_porcupine == null || _voiceProcessor == null)
{
throw new ObjectDisposedException("Porcupine", "Cannot start PorcupineManager - resources have already been released");
}
_voiceProcessor.StartRecording(_porcupine.SampleRate, _porcupine.FrameLength);
}
/// <summary>
/// Stops audio capture and wake word detection
/// </summary>
public void Stop()
{
if (_porcupine == null || _voiceProcessor == null)
{
throw new ObjectDisposedException("Porcupine", "Stop called after PorcupineManager resources were released.");
}
_voiceProcessor.StopRecording();
}
/// <summary>
/// Free resources that were allocated to Porcupine and the voice processor
/// </summary>
public void Delete()
{
if(_voiceProcessor != null)
{
if (_voiceProcessor.IsRecording)
{
_voiceProcessor.StopRecording();
}
_voiceProcessor.OnFrameCaptured -= OnFrameCaptured;
_voiceProcessor = null;
}
if (_porcupine != null) {
_porcupine.Dispose();
_porcupine = null;
}
}
}
}