offline.cs
6.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/// Copyright (c) 2023 Xiaomi Corporation (authors: Fangjun Kuang)
/// Copyright (c) 2023 by manyeyes
using System.Linq;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System;
namespace SherpaOnnx
{
[StructLayout(LayoutKind.Sequential)]
public struct OfflineTransducerModelConfig
{
public OfflineTransducerModelConfig()
{
Encoder = "";
Decoder = "";
Joiner = "";
}
[MarshalAs(UnmanagedType.LPStr)]
public string Encoder;
[MarshalAs(UnmanagedType.LPStr)]
public string Decoder;
[MarshalAs(UnmanagedType.LPStr)]
public string Joiner;
}
[StructLayout(LayoutKind.Sequential)]
public struct OfflineParaformerModelConfig
{
public OfflineParaformerModelConfig()
{
Model = "";
}
[MarshalAs(UnmanagedType.LPStr)]
public string Model;
}
[StructLayout(LayoutKind.Sequential)]
public struct OfflineNemoEncDecCtcModelConfig
{
public OfflineNemoEncDecCtcModelConfig()
{
Model = "";
}
[MarshalAs(UnmanagedType.LPStr)]
public string Model;
}
[StructLayout(LayoutKind.Sequential)]
public struct OfflineLMConfig
{
public OfflineLMConfig()
{
Model = "";
Scale = 0.5F;
}
[MarshalAs(UnmanagedType.LPStr)]
public string Model;
public float Scale;
}
[StructLayout(LayoutKind.Sequential)]
public struct OfflineModelConfig
{
public OfflineModelConfig()
{
Transducer = new OfflineTransducerModelConfig();
Paraformer = new OfflineParaformerModelConfig();
NeMoCtc = new OfflineNemoEncDecCtcModelConfig();
Tokens = "";
NumThreads = 1;
Debug = 0;
}
public OfflineTransducerModelConfig Transducer;
public OfflineParaformerModelConfig Paraformer;
public OfflineNemoEncDecCtcModelConfig NeMoCtc;
[MarshalAs(UnmanagedType.LPStr)]
public string Tokens;
public int NumThreads;
public int Debug;
}
[StructLayout(LayoutKind.Sequential)]
public struct OfflineRecognizerConfig
{
public OfflineRecognizerConfig()
{
FeatConfig = new FeatureConfig();
ModelConfig = new OfflineModelConfig();
LmConfig = new OfflineLMConfig();
DecodingMethod = "greedy_search";
MaxActivePaths = 4;
}
public FeatureConfig FeatConfig;
public OfflineModelConfig ModelConfig;
public OfflineLMConfig LmConfig;
[MarshalAs(UnmanagedType.LPStr)]
public string DecodingMethod;
public int MaxActivePaths;
}
public class OfflineRecognizerResult
{
public OfflineRecognizerResult(IntPtr handle)
{
Impl impl = (Impl)Marshal.PtrToStructure(handle, typeof(Impl));
_text = Marshal.PtrToStringUTF8(impl.Text);
}
[StructLayout(LayoutKind.Sequential)]
struct Impl
{
public IntPtr Text;
}
private String _text;
public String Text => _text;
}
public class OfflineStream : IDisposable
{
public OfflineStream(IntPtr p)
{
_handle = new HandleRef(this, p);
}
public void AcceptWaveform(int sampleRate, float[] samples)
{
AcceptWaveform(Handle, sampleRate, samples, samples.Length);
}
public OfflineRecognizerResult Result
{
get
{
IntPtr h = GetResult(_handle.Handle);
OfflineRecognizerResult result = new OfflineRecognizerResult(h);
DestroyResult(h);
return result;
}
}
~OfflineStream()
{
Cleanup();
}
public void Dispose()
{
Cleanup();
// Prevent the object from being placed on the
// finalization queue
System.GC.SuppressFinalize(this);
}
private void Cleanup()
{
DestroyOfflineStream(Handle);
// Don't permit the handle to be used again.
_handle = new HandleRef(this, IntPtr.Zero);
}
private HandleRef _handle;
public IntPtr Handle => _handle.Handle;
[DllImport(Dll.Filename)]
private static extern void DestroyOfflineStream(IntPtr handle);
[DllImport(Dll.Filename, EntryPoint = "AcceptWaveformOffline")]
private static extern void AcceptWaveform(IntPtr handle, int sampleRate, float[] samples, int n);
[DllImport(Dll.Filename, EntryPoint = "GetOfflineStreamResult")]
private static extern IntPtr GetResult(IntPtr handle);
[DllImport(Dll.Filename, EntryPoint = "DestroyOfflineRecognizerResult")]
private static extern void DestroyResult(IntPtr handle);
}
public class OfflineRecognizer : IDisposable
{
public OfflineRecognizer(OfflineRecognizerConfig config)
{
IntPtr h = CreateOfflineRecognizer(ref config);
_handle = new HandleRef(this, h);
}
public OfflineStream CreateStream()
{
IntPtr p = CreateOfflineStream(_handle.Handle);
return new OfflineStream(p);
}
/// You have to ensure that IsReady(stream) returns true before
/// you call this method
public void Decode(OfflineStream stream)
{
Decode(_handle.Handle, stream.Handle);
}
// The caller should ensure all passed streams are ready for decoding.
public void Decode(IEnumerable<OfflineStream> streams)
{
IntPtr[] ptrs = streams.Select(s => s.Handle).ToArray();
Decode(_handle.Handle, ptrs, ptrs.Length);
}
public void Dispose()
{
Cleanup();
// Prevent the object from being placed on the
// finalization queue
System.GC.SuppressFinalize(this);
}
~OfflineRecognizer()
{
Cleanup();
}
private void Cleanup()
{
DestroyOfflineRecognizer(_handle.Handle);
// Don't permit the handle to be used again.
_handle = new HandleRef(this, IntPtr.Zero);
}
private HandleRef _handle;
[DllImport(Dll.Filename)]
private static extern IntPtr CreateOfflineRecognizer(ref OfflineRecognizerConfig config);
[DllImport(Dll.Filename)]
private static extern void DestroyOfflineRecognizer(IntPtr handle);
[DllImport(Dll.Filename)]
private static extern IntPtr CreateOfflineStream(IntPtr handle);
[DllImport(Dll.Filename, EntryPoint = "DecodeOfflineStream")]
private static extern void Decode(IntPtr handle, IntPtr stream);
[DllImport(Dll.Filename, EntryPoint = "DecodeMultipleOfflineStreams")]
private static extern void Decode(IntPtr handle, IntPtr[] streams, int n);
}
}