using DeepSpeechClient.Interfaces; using DeepSpeechClient.Extensions; using System; using System.IO; using DeepSpeechClient.Enums; using DeepSpeechClient.Models; namespace DeepSpeechClient { /// /// Concrete implementation of . /// public class DeepSpeech : IDeepSpeech { private unsafe IntPtr** _modelStatePP; /// /// Initializes a new instance of class and creates a new acoustic model. /// /// The path to the frozen model graph. /// Thrown when the native binary failed to create the model. public DeepSpeech(string aModelPath) { CreateModel(aModelPath); } #region IDeepSpeech /// /// Create an object providing an interface to a trained DeepSpeech model. /// /// The path to the frozen model graph. /// Thrown when the native binary failed to create the model. private unsafe void CreateModel(string aModelPath) { string exceptionMessage = null; if (string.IsNullOrWhiteSpace(aModelPath)) { exceptionMessage = "Model path cannot be empty."; } if (!File.Exists(aModelPath)) { exceptionMessage = $"Cannot find the model file: {aModelPath}"; } if (exceptionMessage != null) { throw new FileNotFoundException(exceptionMessage); } var resultCode = NativeImp.DS_CreateModel(aModelPath, ref _modelStatePP); EvaluateResultCode(resultCode); } /// /// Get beam width value used by the model. If SetModelBeamWidth was not /// called before, will return the default value loaded from the model file. /// /// Beam width value used by the model. public unsafe uint GetModelBeamWidth() { return NativeImp.DS_GetModelBeamWidth(_modelStatePP); } /// /// Set beam width value used by the model. /// /// The beam width used by the decoder. A larger beam width value generates better results at the cost of decoding time. /// Thrown on failure. public unsafe void SetModelBeamWidth(uint aBeamWidth) { var resultCode = NativeImp.DS_SetModelBeamWidth(_modelStatePP, aBeamWidth); EvaluateResultCode(resultCode); } /// /// Return the sample rate expected by the model. /// /// Sample rate. public unsafe int GetModelSampleRate() { return NativeImp.DS_GetModelSampleRate(_modelStatePP); } /// /// Evaluate the result code and will raise an exception if necessary. /// /// Native result code. private void EvaluateResultCode(ErrorCodes resultCode) { if (resultCode != ErrorCodes.DS_ERR_OK) { throw new ArgumentException(NativeImp.DS_ErrorCodeToErrorMessage((int)resultCode).PtrToString()); } } /// /// Frees associated resources and destroys models objects. /// public unsafe void Dispose() { NativeImp.DS_FreeModel(_modelStatePP); } /// /// Enable decoding using an external scorer. /// /// The path to the external scorer file. /// Thrown when the native binary failed to enable decoding with an external scorer. /// Thrown when cannot find the scorer file. public unsafe void EnableExternalScorer(string aScorerPath) { if (string.IsNullOrWhiteSpace(aScorerPath)) { throw new FileNotFoundException("Path to the scorer file cannot be empty."); } if (!File.Exists(aScorerPath)) { throw new FileNotFoundException($"Cannot find the scorer file: {aScorerPath}"); } var resultCode = NativeImp.DS_EnableExternalScorer(_modelStatePP, aScorerPath); EvaluateResultCode(resultCode); } /// /// Disable decoding using an external scorer. /// /// Thrown when an external scorer is not enabled. public unsafe void DisableExternalScorer() { var resultCode = NativeImp.DS_DisableExternalScorer(_modelStatePP); EvaluateResultCode(resultCode); } /// /// Set hyperparameters alpha and beta of the external scorer. /// /// The alpha hyperparameter of the decoder. Language model weight. /// The beta hyperparameter of the decoder. Word insertion weight. /// Thrown when an external scorer is not enabled. public unsafe void SetScorerAlphaBeta(float aAlpha, float aBeta) { var resultCode = NativeImp.DS_SetScorerAlphaBeta(_modelStatePP, aAlpha, aBeta); EvaluateResultCode(resultCode); } /// /// Feeds audio samples to an ongoing streaming inference. /// /// Instance of the stream to feed the data. /// An array of 16-bit, mono raw audio samples at the appropriate sample rate (matching what the model was trained on). public unsafe void FeedAudioContent(DeepSpeechStream stream, short[] aBuffer, uint aBufferSize) { NativeImp.DS_FeedAudioContent(stream.GetNativePointer(), aBuffer, aBufferSize); } /// /// Closes the ongoing streaming inference, returns the STT result over the whole audio signal. /// /// Instance of the stream to finish. /// The STT result. public unsafe string FinishStream(DeepSpeechStream stream) { return NativeImp.DS_FinishStream(stream.GetNativePointer()).PtrToString(); } /// /// Closes the ongoing streaming inference, returns the STT result over the whole audio signal, including metadata. /// /// Instance of the stream to finish. /// Maximum number of candidate transcripts to return. Returned list might be smaller than this. /// The extended metadata result. public unsafe Metadata FinishStreamWithMetadata(DeepSpeechStream stream, uint aNumResults) { return NativeImp.DS_FinishStreamWithMetadata(stream.GetNativePointer(), aNumResults).PtrToMetadata(); } /// /// Computes the intermediate decoding of an ongoing streaming inference. /// /// Instance of the stream to decode. /// The STT intermediate result. public unsafe string IntermediateDecode(DeepSpeechStream stream) { return NativeImp.DS_IntermediateDecode(stream.GetNativePointer()).PtrToString(); } /// /// Computes the intermediate decoding of an ongoing streaming inference, including metadata. /// /// Instance of the stream to decode. /// Maximum number of candidate transcripts to return. Returned list might be smaller than this. /// The STT intermediate result. public unsafe Metadata IntermediateDecodeWithMetadata(DeepSpeechStream stream, uint aNumResults) { return NativeImp.DS_IntermediateDecodeWithMetadata(stream.GetNativePointer(), aNumResults).PtrToMetadata(); } /// /// Return version of this library. The returned version is a semantic version /// (SemVer 2.0.0). /// public unsafe string Version() { return NativeImp.DS_Version().PtrToString(); } /// /// Creates a new streaming inference state. /// public unsafe DeepSpeechStream CreateStream() { IntPtr** streamingStatePointer = null; var resultCode = NativeImp.DS_CreateStream(_modelStatePP, ref streamingStatePointer); EvaluateResultCode(resultCode); return new DeepSpeechStream(streamingStatePointer); } /// /// Destroy a streaming state without decoding the computed logits. /// This can be used if you no longer need the result of an ongoing streaming /// inference and don't want to perform a costly decode operation. /// public unsafe void FreeStream(DeepSpeechStream stream) { NativeImp.DS_FreeStream(stream.GetNativePointer()); stream.Dispose(); } /// /// Use the DeepSpeech model to perform Speech-To-Text. /// /// A 16-bit, mono raw audio signal at the appropriate sample rate (matching what the model was trained on). /// The number of samples in the audio signal. /// The STT result. Returns NULL on error. public unsafe string SpeechToText(short[] aBuffer, uint aBufferSize) { return NativeImp.DS_SpeechToText(_modelStatePP, aBuffer, aBufferSize).PtrToString(); } /// /// Use the DeepSpeech model to perform Speech-To-Text, return results including metadata. /// /// A 16-bit, mono raw audio signal at the appropriate sample rate (matching what the model was trained on). /// The number of samples in the audio signal. /// Maximum number of candidate transcripts to return. Returned list might be smaller than this. /// The extended metadata. Returns NULL on error. public unsafe Metadata SpeechToTextWithMetadata(short[] aBuffer, uint aBufferSize, uint aNumResults) { return NativeImp.DS_SpeechToTextWithMetadata(_modelStatePP, aBuffer, aBufferSize, aNumResults).PtrToMetadata(); } #endregion } }