Add Flutter example for speaker identification (#894)

This commit is contained in:
Fangjun Kuang
2024-05-21 20:38:52 +08:00
committed by GitHub
parent b445956675
commit 4593ab49d1
46 changed files with 3317 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
// Copyright (c) 2024 Xiaomi Corporation
import 'dart:io';
import 'dart:ffi';
import 'src/sherpa_onnx_bindings.dart';
export 'src/speaker_identification.dart';
export 'src/online_stream.dart';
export 'src/wave_reader.dart';
final DynamicLibrary _dylib = () {
if (Platform.isIOS) {
throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
}
if (Platform.isMacOS) {
return DynamicLibrary.open('libsherpa-onnx-c-api.dylib');
}
if (Platform.isAndroid || Platform.isLinux) {
return DynamicLibrary.open('libsherpa-onnx-c-api.so');
}
if (Platform.isWindows) {
return DynamicLibrary.open('sherpa-onnx-c-api.dll');
}
throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
}();
void initBindings() {
SherpaOnnxBindings.init(_dylib);
}

View File

@@ -0,0 +1,41 @@
// Copyright (c) 2024 Xiaomi Corporation
import 'dart:typed_data';
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import "./sherpa_onnx_bindings.dart";
class OnlineStream {
/// The user has to call OnlineStream.free() to avoid memory leak.
OnlineStream({required this.ptr});
void free() {
SherpaOnnxBindings.destroyOnlineStream?.call(ptr);
ptr = nullptr;
}
/// If you have List<double> data, then you can use
/// Float32List.fromList(data) to convert data to Float32List
///
/// See
/// https://api.flutter.dev/flutter/dart-core/List-class.html
/// and
/// https://api.flutter.dev/flutter/dart-typed_data/Float32List-class.html
void acceptWaveform({required Float32List samples, required int sampleRate}) {
final n = samples.length;
final Pointer<Float> p = calloc<Float>(n);
final pList = p.asTypedList(n);
pList.setAll(0, samples);
SherpaOnnxBindings.onlineStreamAcceptWaveform
?.call(this.ptr, sampleRate, p, n);
calloc.free(p);
}
void inputFinished() {
SherpaOnnxBindings.onlineStreamInputFinished?.call(this.ptr);
}
Pointer<SherpaOnnxOnlineStream> ptr;
}

View File

@@ -0,0 +1,395 @@
// Copyright (c) 2024 Xiaomi Corporation
import 'dart:ffi';
import 'package:ffi/ffi.dart';
final class SherpaOnnxWave extends Struct {
external Pointer<Float> samples;
@Int32()
external int sampleRate;
@Int32()
external int numSamples;
}
final class SherpaOnnxSpeakerEmbeddingExtractorConfig extends Struct {
external Pointer<Utf8> model;
@Int32()
external int numThreads;
@Int32()
external int debug;
external Pointer<Utf8> provider;
}
final class SherpaOnnxOnlineStream extends Opaque {}
final class SherpaOnnxSpeakerEmbeddingExtractor extends Opaque {}
final class SherpaOnnxSpeakerEmbeddingManager extends Opaque {}
typedef SherpaOnnxCreateSpeakerEmbeddingManagerNative
= Pointer<SherpaOnnxSpeakerEmbeddingManager> Function(Int32 dim);
typedef SherpaOnnxCreateSpeakerEmbeddingManager
= Pointer<SherpaOnnxSpeakerEmbeddingManager> Function(int dim);
typedef SherpaOnnxDestroySpeakerEmbeddingManagerNative = Void Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>);
typedef SherpaOnnxDestroySpeakerEmbeddingManager = void Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>);
typedef SherpaOnnxSpeakerEmbeddingManagerAddNative = Int32 Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>, Pointer<Utf8>, Pointer<Float>);
typedef SherpaOnnxSpeakerEmbeddingManagerAdd = int Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>, Pointer<Utf8>, Pointer<Float>);
typedef SherpaOnnxSpeakerEmbeddingManagerAddListFlattenedNative
= Int32 Function(Pointer<SherpaOnnxSpeakerEmbeddingManager>, Pointer<Utf8>,
Pointer<Float>, Int32);
typedef SherpaOnnxSpeakerEmbeddingManagerAddListFlattened = int Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>,
Pointer<Utf8>,
Pointer<Float>,
int);
typedef SherpaOnnxSpeakerEmbeddingManagerRemoveNative = Int32 Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>, Pointer<Utf8>);
typedef SherpaOnnxSpeakerEmbeddingManagerRemove = int Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>, Pointer<Utf8>);
typedef SherpaOnnxSpeakerEmbeddingManagerContainsNative = Int32 Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>, Pointer<Utf8>);
typedef SherpaOnnxSpeakerEmbeddingManagerContains = int Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>, Pointer<Utf8>);
typedef SherpaOnnxSpeakerEmbeddingManagerSearchNative = Pointer<Utf8> Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>, Pointer<Float>, Float);
typedef SherpaOnnxSpeakerEmbeddingManagerSearch = Pointer<Utf8> Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>, Pointer<Float>, double);
typedef SherpaOnnxSpeakerEmbeddingManagerFreeSearchNative = Void Function(
Pointer<Utf8>);
typedef SherpaOnnxSpeakerEmbeddingManagerFreeSearch = void Function(
Pointer<Utf8>);
typedef SherpaOnnxSpeakerEmbeddingManagerNumSpeakersNative = Int32 Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>);
typedef SherpaOnnxSpeakerEmbeddingManagerNumSpeakers = int Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>);
typedef SherpaOnnxSpeakerEmbeddingManagerVerifyNative = Int32 Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>,
Pointer<Utf8>,
Pointer<Float>,
Float);
typedef SherpaOnnxSpeakerEmbeddingManagerVerify = int Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>,
Pointer<Utf8>,
Pointer<Float>,
double);
typedef SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakersNative
= Pointer<Pointer<Utf8>> Function(
Pointer<SherpaOnnxSpeakerEmbeddingManager>);
typedef SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakers
= SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakersNative;
typedef SherpaOnnxSpeakerEmbeddingManagerFreeAllSpeakersNative = Void Function(
Pointer<Pointer<Utf8>>);
typedef SherpaOnnxSpeakerEmbeddingManagerFreeAllSpeakers = void Function(
Pointer<Pointer<Utf8>>);
typedef SherpaOnnxCreateSpeakerEmbeddingExtractorNative
= Pointer<SherpaOnnxSpeakerEmbeddingExtractor> Function(
Pointer<SherpaOnnxSpeakerEmbeddingExtractorConfig>);
typedef SherpaOnnxCreateSpeakerEmbeddingExtractor
= SherpaOnnxCreateSpeakerEmbeddingExtractorNative;
typedef SherpaOnnxDestroySpeakerEmbeddingExtractorNative = Void Function(
Pointer<SherpaOnnxSpeakerEmbeddingExtractor>);
typedef SherpaOnnxDestroySpeakerEmbeddingExtractor = void Function(
Pointer<SherpaOnnxSpeakerEmbeddingExtractor>);
typedef SherpaOnnxSpeakerEmbeddingExtractorDimNative = Int32 Function(
Pointer<SherpaOnnxSpeakerEmbeddingExtractor>);
typedef SherpaOnnxSpeakerEmbeddingExtractorDim = int Function(
Pointer<SherpaOnnxSpeakerEmbeddingExtractor>);
typedef SherpaOnnxSpeakerEmbeddingExtractorCreateStreamNative
= Pointer<SherpaOnnxOnlineStream> Function(
Pointer<SherpaOnnxSpeakerEmbeddingExtractor>);
typedef SherpaOnnxSpeakerEmbeddingExtractorCreateStream
= SherpaOnnxSpeakerEmbeddingExtractorCreateStreamNative;
typedef DestroyOnlineStreamNative = Void Function(
Pointer<SherpaOnnxOnlineStream>);
typedef DestroyOnlineStream = void Function(Pointer<SherpaOnnxOnlineStream>);
typedef OnlineStreamAcceptWaveformNative = Void Function(
Pointer<SherpaOnnxOnlineStream>,
Int32 sample_rate,
Pointer<Float>,
Int32 n);
typedef OnlineStreamAcceptWaveform = void Function(
Pointer<SherpaOnnxOnlineStream>, int sample_rate, Pointer<Float>, int n);
typedef OnlineStreamInputFinishedNative = Void Function(
Pointer<SherpaOnnxOnlineStream>);
typedef OnlineStreamInputFinished = void Function(
Pointer<SherpaOnnxOnlineStream>);
typedef SherpaOnnxSpeakerEmbeddingExtractorIsReadyNative = Int32 Function(
Pointer<SherpaOnnxSpeakerEmbeddingExtractor>,
Pointer<SherpaOnnxOnlineStream>);
typedef SherpaOnnxSpeakerEmbeddingExtractorIsReady = int Function(
Pointer<SherpaOnnxSpeakerEmbeddingExtractor>,
Pointer<SherpaOnnxOnlineStream>);
typedef SherpaOnnxSpeakerEmbeddingExtractorComputeEmbeddingNative
= Pointer<Float> Function(Pointer<SherpaOnnxSpeakerEmbeddingExtractor>,
Pointer<SherpaOnnxOnlineStream>);
typedef SherpaOnnxSpeakerEmbeddingExtractorComputeEmbedding
= SherpaOnnxSpeakerEmbeddingExtractorComputeEmbeddingNative;
typedef SherpaOnnxSpeakerEmbeddingExtractorDestroyEmbeddingNative = Void
Function(Pointer<Float>);
typedef SherpaOnnxSpeakerEmbeddingExtractorDestroyEmbedding = void Function(
Pointer<Float>);
typedef SherpaOnnxReadWaveNative = Pointer<SherpaOnnxWave> Function(
Pointer<Utf8>);
typedef SherpaOnnxReadWave = SherpaOnnxReadWaveNative;
typedef SherpaOnnxFreeWaveNative = Void Function(Pointer<SherpaOnnxWave>);
typedef SherpaOnnxFreeWave = void Function(Pointer<SherpaOnnxWave>);
class SherpaOnnxBindings {
static SherpaOnnxCreateSpeakerEmbeddingExtractor?
createSpeakerEmbeddingExtractor;
static SherpaOnnxDestroySpeakerEmbeddingExtractor?
destroySpeakerEmbeddingExtractor;
static SherpaOnnxSpeakerEmbeddingExtractorDim? speakerEmbeddingExtractorDim;
static SherpaOnnxSpeakerEmbeddingExtractorCreateStream?
speakerEmbeddingExtractorCreateStream;
static SherpaOnnxSpeakerEmbeddingExtractorComputeEmbedding?
speakerEmbeddingExtractorComputeEmbedding;
static SherpaOnnxSpeakerEmbeddingExtractorDestroyEmbedding?
speakerEmbeddingExtractorDestroyEmbedding;
static DestroyOnlineStream? destroyOnlineStream;
static OnlineStreamAcceptWaveform? onlineStreamAcceptWaveform;
static OnlineStreamInputFinished? onlineStreamInputFinished;
static SherpaOnnxSpeakerEmbeddingExtractorIsReady?
speakerEmbeddingExtractorIsReady;
static SherpaOnnxCreateSpeakerEmbeddingManager? createSpeakerEmbeddingManager;
static SherpaOnnxDestroySpeakerEmbeddingManager?
destroySpeakerEmbeddingManager;
static SherpaOnnxSpeakerEmbeddingManagerAdd? speakerEmbeddingManagerAdd;
static SherpaOnnxSpeakerEmbeddingManagerAddListFlattened?
speakerEmbeddingManagerAddListFlattened;
static SherpaOnnxSpeakerEmbeddingManagerRemove? speakerEmbeddingManagerRemove;
static SherpaOnnxSpeakerEmbeddingManagerContains?
speakerEmbeddingManagerContains;
static SherpaOnnxSpeakerEmbeddingManagerSearch? speakerEmbeddingManagerSearch;
static SherpaOnnxSpeakerEmbeddingManagerFreeSearch?
speakerEmbeddingManagerFreeSearch;
static SherpaOnnxSpeakerEmbeddingManagerNumSpeakers?
speakerEmbeddingManagerNumSpeakers;
static SherpaOnnxSpeakerEmbeddingManagerVerify? speakerEmbeddingManagerVerify;
static SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakers?
speakerEmbeddingManagerGetAllSpeakers;
static SherpaOnnxSpeakerEmbeddingManagerFreeAllSpeakers?
speakerEmbeddingManagerFreeAllSpeakers;
static SherpaOnnxReadWave? readWave;
static SherpaOnnxFreeWave? freeWave;
static void init(DynamicLibrary dynamicLibrary) {
createSpeakerEmbeddingExtractor ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxCreateSpeakerEmbeddingExtractor>>(
'SherpaOnnxCreateSpeakerEmbeddingExtractor')
.asFunction();
destroySpeakerEmbeddingExtractor ??= dynamicLibrary
.lookup<
NativeFunction<
SherpaOnnxDestroySpeakerEmbeddingExtractorNative>>(
'SherpaOnnxDestroySpeakerEmbeddingExtractor')
.asFunction();
speakerEmbeddingExtractorDim ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxSpeakerEmbeddingExtractorDimNative>>(
'SherpaOnnxSpeakerEmbeddingExtractorDim')
.asFunction();
speakerEmbeddingExtractorCreateStream ??= dynamicLibrary
.lookup<
NativeFunction<
SherpaOnnxSpeakerEmbeddingExtractorCreateStreamNative>>(
'SherpaOnnxSpeakerEmbeddingExtractorCreateStream')
.asFunction();
speakerEmbeddingExtractorComputeEmbedding ??= dynamicLibrary
.lookup<
NativeFunction<
SherpaOnnxSpeakerEmbeddingExtractorComputeEmbeddingNative>>(
'SherpaOnnxSpeakerEmbeddingExtractorComputeEmbedding')
.asFunction();
speakerEmbeddingExtractorDestroyEmbedding ??= dynamicLibrary
.lookup<
NativeFunction<
SherpaOnnxSpeakerEmbeddingExtractorDestroyEmbeddingNative>>(
'SherpaOnnxSpeakerEmbeddingExtractorDestroyEmbedding')
.asFunction();
destroyOnlineStream ??= dynamicLibrary
.lookup<NativeFunction<DestroyOnlineStreamNative>>(
'DestroyOnlineStream')
.asFunction();
onlineStreamAcceptWaveform ??= dynamicLibrary
.lookup<NativeFunction<OnlineStreamAcceptWaveformNative>>(
'AcceptWaveform')
.asFunction();
onlineStreamInputFinished ??= dynamicLibrary
.lookup<NativeFunction<OnlineStreamInputFinishedNative>>(
'InputFinished')
.asFunction();
speakerEmbeddingExtractorIsReady ??= dynamicLibrary
.lookup<
NativeFunction<
SherpaOnnxSpeakerEmbeddingExtractorIsReadyNative>>(
'SherpaOnnxSpeakerEmbeddingExtractorIsReady')
.asFunction();
createSpeakerEmbeddingManager ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxCreateSpeakerEmbeddingManagerNative>>(
'SherpaOnnxCreateSpeakerEmbeddingManager')
.asFunction();
destroySpeakerEmbeddingManager ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxDestroySpeakerEmbeddingManagerNative>>(
'SherpaOnnxDestroySpeakerEmbeddingManager')
.asFunction();
speakerEmbeddingManagerAdd ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxSpeakerEmbeddingManagerAddNative>>(
'SherpaOnnxSpeakerEmbeddingManagerAdd')
.asFunction();
speakerEmbeddingManagerAddListFlattened ??= dynamicLibrary
.lookup<
NativeFunction<
SherpaOnnxSpeakerEmbeddingManagerAddListFlattenedNative>>(
'SherpaOnnxSpeakerEmbeddingManagerAddListFlattened')
.asFunction();
speakerEmbeddingManagerRemove ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxSpeakerEmbeddingManagerRemoveNative>>(
'SherpaOnnxSpeakerEmbeddingManagerRemove')
.asFunction();
speakerEmbeddingManagerContains ??= dynamicLibrary
.lookup<
NativeFunction<
SherpaOnnxSpeakerEmbeddingManagerContainsNative>>(
'SherpaOnnxSpeakerEmbeddingManagerContains')
.asFunction();
speakerEmbeddingManagerSearch ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxSpeakerEmbeddingManagerSearchNative>>(
'SherpaOnnxSpeakerEmbeddingManagerSearch')
.asFunction();
speakerEmbeddingManagerFreeSearch ??= dynamicLibrary
.lookup<
NativeFunction<
SherpaOnnxSpeakerEmbeddingManagerFreeSearchNative>>(
'SherpaOnnxSpeakerEmbeddingManagerFreeSearch')
.asFunction();
speakerEmbeddingManagerNumSpeakers ??= dynamicLibrary
.lookup<
NativeFunction<
SherpaOnnxSpeakerEmbeddingManagerNumSpeakersNative>>(
'SherpaOnnxSpeakerEmbeddingManagerNumSpeakers')
.asFunction();
speakerEmbeddingManagerVerify ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxSpeakerEmbeddingManagerVerifyNative>>(
'SherpaOnnxSpeakerEmbeddingManagerVerify')
.asFunction();
speakerEmbeddingManagerGetAllSpeakers ??= dynamicLibrary
.lookup<
NativeFunction<
SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakersNative>>(
'SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakers')
.asFunction();
speakerEmbeddingManagerFreeAllSpeakers ??= dynamicLibrary
.lookup<
NativeFunction<
SherpaOnnxSpeakerEmbeddingManagerFreeAllSpeakersNative>>(
'SherpaOnnxSpeakerEmbeddingManagerFreeAllSpeakers')
.asFunction();
readWave ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxReadWaveNative>>('SherpaOnnxReadWave')
.asFunction();
freeWave ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxFreeWaveNative>>('SherpaOnnxFreeWave')
.asFunction();
}
}

View File

@@ -0,0 +1,269 @@
// Copyright (c) 2024 Xiaomi Corporation
import 'dart:ffi';
import 'dart:typed_data';
import 'package:ffi/ffi.dart';
import "./sherpa_onnx_bindings.dart";
import "./online_stream.dart";
class SpeakerEmbeddingExtractorConfig {
const SpeakerEmbeddingExtractorConfig(
{required this.model,
this.numThreads = 1,
this.debug = true,
this.provider = "cpu"});
@override
String toString() {
return "SpeakerEmbeddingExtractorConfig(model: $model, numThreads: $numThreads, debug: $debug, provider: $provider)";
}
final String model;
final int numThreads;
final bool debug;
final String provider;
}
class SpeakerEmbeddingExtractor {
SpeakerEmbeddingExtractor._({required this.ptr, required this.dim});
/// The user is responsible to call the SpeakerEmbeddingExtractor.free()
/// method of the returned instance to avoid memory leak.
factory SpeakerEmbeddingExtractor(
{required SpeakerEmbeddingExtractorConfig config}) {
final c = calloc<SherpaOnnxSpeakerEmbeddingExtractorConfig>();
final modelPtr = config.model.toNativeUtf8();
c.ref.model = modelPtr;
c.ref.numThreads = config.numThreads;
c.ref.debug = config.debug ? 1 : 0;
final providerPtr = config.provider.toNativeUtf8();
c.ref.provider = providerPtr;
final ptr =
SherpaOnnxBindings.createSpeakerEmbeddingExtractor?.call(c) ?? nullptr;
calloc.free(providerPtr);
calloc.free(modelPtr);
calloc.free(c);
final dim = SherpaOnnxBindings.speakerEmbeddingExtractorDim?.call(ptr) ?? 0;
return SpeakerEmbeddingExtractor._(ptr: ptr, dim: dim);
}
void free() {
SherpaOnnxBindings.destroySpeakerEmbeddingExtractor?.call(ptr);
ptr = nullptr;
}
/// The user has to invoke stream.free() on the returned instance
/// to avoid memory leak
OnlineStream createStream() {
final p =
SherpaOnnxBindings.speakerEmbeddingExtractorCreateStream?.call(ptr) ??
nullptr;
return OnlineStream(ptr: p);
}
bool isReady(OnlineStream stream) {
final int ready = SherpaOnnxBindings.speakerEmbeddingExtractorIsReady
?.call(this.ptr, stream.ptr) ??
0;
return ready == 1;
}
Float32List compute(OnlineStream stream) {
final Pointer<Float> embedding = SherpaOnnxBindings
.speakerEmbeddingExtractorComputeEmbedding
?.call(this.ptr, stream.ptr) ??
nullptr;
if (embedding == nullptr) {
return Float32List(0);
}
final embeddingList = embedding.asTypedList(this.dim);
final ans = Float32List(this.dim);
ans.setAll(0, embeddingList);
SherpaOnnxBindings.speakerEmbeddingExtractorDestroyEmbedding
?.call(embedding);
return ans;
}
Pointer<SherpaOnnxSpeakerEmbeddingExtractor> ptr;
final int dim;
}
class SpeakerEmbeddingManager {
SpeakerEmbeddingManager._({required this.ptr, required this.dim});
// The user has to use SpeakerEmbeddingManager.free() to avoid memory leak
factory SpeakerEmbeddingManager(int dim) {
final p =
SherpaOnnxBindings.createSpeakerEmbeddingManager?.call(dim) ?? nullptr;
return SpeakerEmbeddingManager._(ptr: p, dim: dim);
}
void free() {
SherpaOnnxBindings.destroySpeakerEmbeddingManager?.call(this.ptr);
this.ptr = nullptr;
}
/// Return true if added successfully; return false otherwise
bool add({required String name, required Float32List embedding}) {
assert(embedding.length == this.dim, "${embedding.length} vs ${this.dim}");
final Pointer<Utf8> namePtr = name.toNativeUtf8();
final int n = embedding.length;
final Pointer<Float> p = calloc<Float>(n);
final pList = p.asTypedList(n);
pList.setAll(0, embedding);
final int ok = SherpaOnnxBindings.speakerEmbeddingManagerAdd
?.call(this.ptr, namePtr, p) ??
0;
calloc.free(p);
calloc.free(namePtr);
return ok == 1;
}
bool addMulti(
{required String name, required List<Float32List> embeddingList}) {
final Pointer<Utf8> namePtr = name.toNativeUtf8();
final int n = embeddingList.length;
final Pointer<Float> p = calloc<Float>(n * this.dim);
final pList = p.asTypedList(n * this.dim);
int offset = 0;
for (final e in embeddingList) {
assert(e.length == this.dim, "${e.length} vs ${this.dim}");
pList.setAll(offset, e);
offset += this.dim;
}
final int ok = SherpaOnnxBindings.speakerEmbeddingManagerAddListFlattened
?.call(this.ptr, namePtr, p, n) ??
0;
calloc.free(p);
calloc.free(namePtr);
return ok == 1;
}
bool contains(String name) {
final Pointer<Utf8> namePtr = name.toNativeUtf8();
final int found = SherpaOnnxBindings.speakerEmbeddingManagerContains
?.call(this.ptr, namePtr) ??
0;
calloc.free(namePtr);
return found == 1;
}
bool remove(String name) {
final Pointer<Utf8> namePtr = name.toNativeUtf8();
final int ok = SherpaOnnxBindings.speakerEmbeddingManagerRemove
?.call(this.ptr, namePtr) ??
0;
calloc.free(namePtr);
return ok == 1;
}
/// Return an empty string if no speaker is found
String search({required Float32List embedding, required double threshold}) {
assert(embedding.length == this.dim);
final Pointer<Float> p = calloc<Float>(this.dim);
final pList = p.asTypedList(this.dim);
pList.setAll(0, embedding);
final Pointer<Utf8> name = SherpaOnnxBindings.speakerEmbeddingManagerSearch
?.call(this.ptr, p, threshold) ??
nullptr;
calloc.free(p);
if (name == nullptr) {
return '';
}
final String ans = name.toDartString();
SherpaOnnxBindings.speakerEmbeddingManagerFreeSearch?.call(name);
return ans;
}
bool verify(
{required String name,
required Float32List embedding,
required double threshold}) {
assert(embedding.length == this.dim);
final Pointer<Utf8> namePtr = name.toNativeUtf8();
final Pointer<Float> p = calloc<Float>(this.dim);
final pList = p.asTypedList(this.dim);
pList.setAll(0, embedding);
final int ok = SherpaOnnxBindings.speakerEmbeddingManagerVerify
?.call(this.ptr, namePtr, p, threshold) ??
0;
calloc.free(p);
calloc.free(namePtr);
return ok == 1;
}
int get numSpeakers =>
SherpaOnnxBindings.speakerEmbeddingManagerNumSpeakers?.call(this.ptr) ??
0;
List<String> get allSpeakerNames {
int n = this.numSpeakers;
if (n == 0) {
return <String>[];
}
final Pointer<Pointer<Utf8>> names = SherpaOnnxBindings
.speakerEmbeddingManagerGetAllSpeakers
?.call(this.ptr) ??
nullptr;
if (names == nullptr) {
return <String>[];
}
final ans = <String>[];
// see https://api.flutter.dev/flutter/dart-ffi/PointerPointer.html
for (int i = 0; i != n; ++i) {
String name = names[i].toDartString();
ans.add(name);
}
SherpaOnnxBindings.speakerEmbeddingManagerFreeAllSpeakers?.call(names);
return ans;
}
Pointer<SherpaOnnxSpeakerEmbeddingManager> ptr;
final int dim;
}

View File

@@ -0,0 +1,32 @@
// Copyright (c) 2024 Xiaomi Corporation
import 'dart:ffi';
import 'dart:typed_data';
import 'package:ffi/ffi.dart';
import "./sherpa_onnx_bindings.dart";
class WaveData {
WaveData({required this.samples, required this.sampleRate});
/// normalized to [-1, 1]
Float32List samples;
int sampleRate;
}
WaveData readWave(String filename) {
final Pointer<Utf8> str = filename.toNativeUtf8();
Pointer<SherpaOnnxWave> wave =
SherpaOnnxBindings.readWave?.call(str) ?? nullptr;
calloc.free(str);
if (wave == nullptr) {
return WaveData(samples: Float32List(0), sampleRate: 0);
}
final samples = wave.ref.samples.asTypedList(wave.ref.numSamples);
final newSamples = Float32List.fromList(samples);
int sampleRate = wave.ref.sampleRate;
SherpaOnnxBindings.freeWave?.call(wave);
return WaveData(samples: newSamples, sampleRate: sampleRate);
}