sherpa-ncnn.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // Copyright (c) 2023 Xiaomi Corporation (authors: Fangjun Kuang)
  2. using System.Runtime.InteropServices;
  3. using System;
  4. using System.Text;
  5. namespace SherpaNcnn
  6. {
  7. [StructLayout(LayoutKind.Sequential)]
  8. public struct TransducerModelConfig
  9. {
  10. [MarshalAs(UnmanagedType.LPStr)]
  11. public string EncoderParam;
  12. [MarshalAs(UnmanagedType.LPStr)]
  13. public string EncoderBin;
  14. [MarshalAs(UnmanagedType.LPStr)]
  15. public string DecoderParam;
  16. [MarshalAs(UnmanagedType.LPStr)]
  17. public string DecoderBin;
  18. [MarshalAs(UnmanagedType.LPStr)]
  19. public string JoinerParam;
  20. [MarshalAs(UnmanagedType.LPStr)]
  21. public string JoinerBin;
  22. [MarshalAs(UnmanagedType.LPStr)]
  23. public string Tokens;
  24. public int UseVulkanCompute;
  25. public int NumThreads;
  26. }
  27. [StructLayout(LayoutKind.Sequential)]
  28. public struct TransducerDecoderConfig
  29. {
  30. [MarshalAs(UnmanagedType.LPStr)]
  31. public string DecodingMethod;
  32. public int NumActivePaths;
  33. }
  34. [StructLayout(LayoutKind.Sequential)]
  35. public struct FeatureConfig
  36. {
  37. public float SampleRate;
  38. public int FeatureDim;
  39. }
  40. [StructLayout(LayoutKind.Sequential)]
  41. public struct OnlineRecognizerConfig
  42. {
  43. public FeatureConfig FeatConfig;
  44. public TransducerModelConfig ModelConfig;
  45. public TransducerDecoderConfig DecoderConfig;
  46. public int EnableEndpoint;
  47. public float Rule1MinTrailingSilence;
  48. public float Rule2MinTrailingSilence;
  49. public float Rule3MinUtteranceLength;
  50. [MarshalAs(UnmanagedType.LPStr)]
  51. public string HotwordsFile;
  52. public float HotwordsScore;
  53. }
  54. // please see
  55. // https://www.mono-project.com/docs/advanced/pinvoke/#gc-safe-pinvoke-code
  56. // https://www.mono-project.com/docs/advanced/pinvoke/#properly-disposing-of-resources
  57. public class OnlineRecognizer : IDisposable
  58. {
  59. public OnlineRecognizer(OnlineRecognizerConfig config)
  60. {
  61. IntPtr h = CreateOnlineRecognizer(ref config);
  62. _handle = new HandleRef(this, h);
  63. }
  64. public OnlineStream CreateStream()
  65. {
  66. IntPtr p = CreateOnlineStream(_handle.Handle);
  67. return new OnlineStream(p);
  68. }
  69. public bool IsReady(OnlineStream stream)
  70. {
  71. return IsReady(_handle.Handle, stream.Handle) != 0;
  72. }
  73. public bool IsEndpoint(OnlineStream stream)
  74. {
  75. return IsEndpoint(_handle.Handle, stream.Handle) != 0;
  76. }
  77. public void Reset(OnlineStream stream)
  78. {
  79. Reset(_handle.Handle, stream.Handle);
  80. }
  81. public void Decode(OnlineStream stream)
  82. {
  83. Decode(_handle.Handle, stream.Handle);
  84. }
  85. public OnlineRecognizerResult GetResult(OnlineStream stream)
  86. {
  87. IntPtr h = GetResult(_handle.Handle, stream.Handle);
  88. OnlineRecognizerResult result = new OnlineRecognizerResult(h);
  89. DestroyResult(h);
  90. return result;
  91. }
  92. public void Dispose()
  93. {
  94. Cleanup();
  95. // Prevent the object from being placed on the
  96. // finalization queue
  97. System.GC.SuppressFinalize(this);
  98. }
  99. ~OnlineRecognizer()
  100. {
  101. Cleanup();
  102. }
  103. private void Cleanup()
  104. {
  105. DestroyOnlineRecognizer(_handle.Handle);
  106. // Don't permit the handle to be used again.
  107. _handle = new HandleRef(this, IntPtr.Zero);
  108. }
  109. private HandleRef _handle;
  110. private const string dllName = "sherpa-ncnn-c-api";
  111. [DllImport(dllName, EntryPoint = "CreateRecognizer")]
  112. private static extern IntPtr CreateOnlineRecognizer(ref OnlineRecognizerConfig config);
  113. [DllImport(dllName, EntryPoint = "DestroyRecognizer")]
  114. private static extern void DestroyOnlineRecognizer(IntPtr handle);
  115. [DllImport(dllName, EntryPoint = "CreateStream")]
  116. private static extern IntPtr CreateOnlineStream(IntPtr handle);
  117. [DllImport(dllName)]
  118. private static extern int IsReady(IntPtr handle, IntPtr stream);
  119. [DllImport(dllName)]
  120. private static extern int IsEndpoint(IntPtr handle, IntPtr stream);
  121. [DllImport(dllName)]
  122. private static extern void Reset(IntPtr handle, IntPtr stream);
  123. [DllImport(dllName, EntryPoint = "Decode")]
  124. private static extern void Decode(IntPtr handle, IntPtr stream);
  125. [DllImport(dllName)]
  126. private static extern IntPtr GetResult(IntPtr handle, IntPtr stream);
  127. [DllImport(dllName)]
  128. private static extern void DestroyResult(IntPtr result);
  129. }
  130. public class OnlineStream : IDisposable
  131. {
  132. public OnlineStream(IntPtr p)
  133. {
  134. _handle = new HandleRef(this, p);
  135. }
  136. public void AcceptWaveform(float sampleRate, float[] samples)
  137. {
  138. AcceptWaveform(Handle, sampleRate, samples, samples.Length);
  139. }
  140. public void InputFinished()
  141. {
  142. InputFinished(Handle);
  143. }
  144. ~OnlineStream()
  145. {
  146. Cleanup();
  147. }
  148. public void Dispose()
  149. {
  150. Cleanup();
  151. // Prevent the object from being placed on the
  152. // finalization queue
  153. System.GC.SuppressFinalize(this);
  154. }
  155. private void Cleanup()
  156. {
  157. DestroyOnlineStream(Handle);
  158. // Don't permit the handle to be used again.
  159. _handle = new HandleRef(this, IntPtr.Zero);
  160. }
  161. private HandleRef _handle;
  162. public IntPtr Handle => _handle.Handle;
  163. private const string dllName = "sherpa-ncnn-c-api";
  164. [DllImport(dllName, EntryPoint = "DestroyStream")]
  165. private static extern void DestroyOnlineStream(IntPtr handle);
  166. [DllImport(dllName)]
  167. private static extern void AcceptWaveform(IntPtr handle, float sampleRate, float[] samples, int n);
  168. [DllImport(dllName)]
  169. private static extern void InputFinished(IntPtr handle);
  170. }
  171. public class OnlineRecognizerResult
  172. {
  173. public OnlineRecognizerResult(IntPtr handle)
  174. {
  175. Impl impl = (Impl)Marshal.PtrToStructure(handle, typeof(Impl));
  176. // PtrToStringUTF8() requires .net standard 2.1
  177. // _text = Marshal.PtrToStringUTF8(impl.Text);
  178. int length = 0;
  179. unsafe
  180. {
  181. byte* buffer = (byte*)impl.Text;
  182. while (*buffer != 0)
  183. {
  184. ++buffer;
  185. }
  186. length = (int)(buffer - (byte*)impl.Text);
  187. }
  188. byte[] stringBuffer = new byte[length];
  189. Marshal.Copy(impl.Text, stringBuffer, 0, length);
  190. _text = Encoding.UTF8.GetString(stringBuffer);
  191. }
  192. [StructLayout(LayoutKind.Sequential)]
  193. struct Impl
  194. {
  195. public IntPtr Text;
  196. public IntPtr Tokens;
  197. public IntPtr Timestamps;
  198. int Count;
  199. }
  200. private String _text;
  201. public String Text => _text;
  202. }
  203. }