/// Copyright (c) 2024.5 by 东风破 using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; namespace SherpaOnnx { public class SpeakerEmbeddingManager : IDisposable { public SpeakerEmbeddingManager(int dim) { IntPtr h = SherpaOnnxCreateSpeakerEmbeddingManager(dim); _handle = new HandleRef(this, h); this._dim = dim; } public bool Add(string name, float[] v) { byte[] utf8Name = Encoding.UTF8.GetBytes(name); byte[] utf8NameWithNull = new byte[utf8Name.Length + 1]; // +1 for null terminator Array.Copy(utf8Name, utf8NameWithNull, utf8Name.Length); utf8NameWithNull[utf8Name.Length] = 0; // Null terminator return SherpaOnnxSpeakerEmbeddingManagerAdd(_handle.Handle, utf8NameWithNull, v) == 1; } public bool Add(string name, ICollection v_list) { int n = v_list.Count; float[] v = new float[n * _dim]; int i = 0; foreach (var item in v_list) { item.CopyTo(v, i); i += _dim; } byte[] utf8Name = Encoding.UTF8.GetBytes(name); byte[] utf8NameWithNull = new byte[utf8Name.Length + 1]; // +1 for null terminator Array.Copy(utf8Name, utf8NameWithNull, utf8Name.Length); utf8NameWithNull[utf8Name.Length] = 0; // Null terminator return SherpaOnnxSpeakerEmbeddingManagerAddListFlattened(_handle.Handle, utf8NameWithNull, v, n) == 1; } public bool Remove(string name) { byte[] utf8Name = Encoding.UTF8.GetBytes(name); byte[] utf8NameWithNull = new byte[utf8Name.Length + 1]; // +1 for null terminator Array.Copy(utf8Name, utf8NameWithNull, utf8Name.Length); utf8NameWithNull[utf8Name.Length] = 0; // Null terminator return SherpaOnnxSpeakerEmbeddingManagerRemove(_handle.Handle, utf8NameWithNull) == 1; } public string Search(float[] v, float threshold) { IntPtr p = SherpaOnnxSpeakerEmbeddingManagerSearch(_handle.Handle, v, threshold); string s = ""; int length = 0; unsafe { byte* b = (byte*)p; if (b != null) { while (*b != 0) { ++b; length += 1; } } } if (length > 0) { byte[] stringBuffer = new byte[length]; Marshal.Copy(p, stringBuffer, 0, length); s = Encoding.UTF8.GetString(stringBuffer); } SherpaOnnxSpeakerEmbeddingManagerFreeSearch(p); return s; } public bool Verify(string name, float[] v, float threshold) { byte[] utf8Name = Encoding.UTF8.GetBytes(name); byte[] utf8NameWithNull = new byte[utf8Name.Length + 1]; // +1 for null terminator Array.Copy(utf8Name, utf8NameWithNull, utf8Name.Length); utf8NameWithNull[utf8Name.Length] = 0; // Null terminator return SherpaOnnxSpeakerEmbeddingManagerVerify(_handle.Handle, utf8NameWithNull, v, threshold) == 1; } public bool Contains(string name) { byte[] utf8Name = Encoding.UTF8.GetBytes(name); byte[] utf8NameWithNull = new byte[utf8Name.Length + 1]; // +1 for null terminator Array.Copy(utf8Name, utf8NameWithNull, utf8Name.Length); utf8NameWithNull[utf8Name.Length] = 0; // Null terminator return SherpaOnnxSpeakerEmbeddingManagerContains(_handle.Handle, utf8NameWithNull) == 1; } public string[] GetAllSpeakers() { if (NumSpeakers == 0) { return new string[] { }; } IntPtr names = SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakers(_handle.Handle); string[] ans = new string[NumSpeakers]; unsafe { byte** p = (byte**)names; for (int i = 0; i != NumSpeakers; i++) { int length = 0; byte* s = p[i]; while (*s != 0) { ++s; length += 1; } byte[] stringBuffer = new byte[length]; Marshal.Copy((IntPtr)p[i], stringBuffer, 0, length); ans[i] = Encoding.UTF8.GetString(stringBuffer); } } SherpaOnnxSpeakerEmbeddingManagerFreeAllSpeakers(names); return ans; } public void Dispose() { Cleanup(); // Prevent the object from being placed on the // finalization queue System.GC.SuppressFinalize(this); } ~SpeakerEmbeddingManager() { Cleanup(); } private void Cleanup() { SherpaOnnxDestroySpeakerEmbeddingManager(_handle.Handle); // Don't permit the handle to be used again. _handle = new HandleRef(this, IntPtr.Zero); } public int NumSpeakers { get { return SherpaOnnxSpeakerEmbeddingManagerNumSpeakers(_handle.Handle); } } private HandleRef _handle; private int _dim; [DllImport(Dll.Filename)] private static extern IntPtr SherpaOnnxCreateSpeakerEmbeddingManager(int dim); [DllImport(Dll.Filename)] private static extern void SherpaOnnxDestroySpeakerEmbeddingManager(IntPtr handle); [DllImport(Dll.Filename)] private static extern int SherpaOnnxSpeakerEmbeddingManagerAdd(IntPtr handle, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1)] byte[] utf8Name, float[] v); [DllImport(Dll.Filename)] private static extern int SherpaOnnxSpeakerEmbeddingManagerAddListFlattened(IntPtr handle, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1)] byte[] utf8Name, float[] v, int n); [DllImport(Dll.Filename)] private static extern int SherpaOnnxSpeakerEmbeddingManagerRemove(IntPtr handle, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1)] byte[] utf8Name); [DllImport(Dll.Filename)] private static extern IntPtr SherpaOnnxSpeakerEmbeddingManagerSearch(IntPtr handle, float[] v, float threshold); [DllImport(Dll.Filename)] private static extern void SherpaOnnxSpeakerEmbeddingManagerFreeSearch(IntPtr p); [DllImport(Dll.Filename)] private static extern int SherpaOnnxSpeakerEmbeddingManagerVerify(IntPtr handle, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1)] byte[] utf8Name, float[] v, float threshold); [DllImport(Dll.Filename)] private static extern int SherpaOnnxSpeakerEmbeddingManagerContains(IntPtr handle, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1)] byte[] utf8Name); [DllImport(Dll.Filename)] private static extern int SherpaOnnxSpeakerEmbeddingManagerNumSpeakers(IntPtr handle); [DllImport(Dll.Filename)] private static extern IntPtr SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakers(IntPtr handle); [DllImport(Dll.Filename)] private static extern void SherpaOnnxSpeakerEmbeddingManagerFreeAllSpeakers(IntPtr names); } }