Add Flutter example for speaker identification (#894)
This commit is contained in:
30
sherpa-onnx/flutter/lib/sherpa_onnx.dart
Normal file
30
sherpa-onnx/flutter/lib/sherpa_onnx.dart
Normal 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);
|
||||
}
|
||||
41
sherpa-onnx/flutter/lib/src/online_stream.dart
Normal file
41
sherpa-onnx/flutter/lib/src/online_stream.dart
Normal 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;
|
||||
}
|
||||
395
sherpa-onnx/flutter/lib/src/sherpa_onnx_bindings.dart
Normal file
395
sherpa-onnx/flutter/lib/src/sherpa_onnx_bindings.dart
Normal 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();
|
||||
}
|
||||
}
|
||||
269
sherpa-onnx/flutter/lib/src/speaker_identification.dart
Normal file
269
sherpa-onnx/flutter/lib/src/speaker_identification.dart
Normal 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;
|
||||
}
|
||||
32
sherpa-onnx/flutter/lib/src/wave_reader.dart
Normal file
32
sherpa-onnx/flutter/lib/src/wave_reader.dart
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user