Add Dart API for VAD (#904)
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ffi';
|
||||
import 'dart:typed_data';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import "./sherpa_onnx_bindings.dart";
|
||||
|
||||
import './sherpa_onnx_bindings.dart';
|
||||
|
||||
class OnlineStream {
|
||||
/// The user has to call OnlineStream.free() to avoid memory leak.
|
||||
|
||||
@@ -2,6 +2,47 @@
|
||||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
final class SherpaOnnxSileroVadModelConfig extends Struct {
|
||||
external Pointer<Utf8> model;
|
||||
|
||||
@Float()
|
||||
external double threshold;
|
||||
|
||||
@Float()
|
||||
external double minSilenceDuration;
|
||||
|
||||
@Float()
|
||||
external double minSpeechDuration;
|
||||
|
||||
@Int32()
|
||||
external int windowSize;
|
||||
}
|
||||
|
||||
final class SherpaOnnxVadModelConfig extends Struct {
|
||||
external SherpaOnnxSileroVadModelConfig sileroVad;
|
||||
|
||||
@Int32()
|
||||
external int sampleRate;
|
||||
|
||||
@Int32()
|
||||
external int numThreads;
|
||||
|
||||
external Pointer<Utf8> provider;
|
||||
|
||||
@Int32()
|
||||
external int debug;
|
||||
}
|
||||
|
||||
final class SherpaOnnxSpeechSegment extends Struct {
|
||||
@Int32()
|
||||
external int start;
|
||||
|
||||
external Pointer<Float> samples;
|
||||
|
||||
@Int32()
|
||||
external int n;
|
||||
}
|
||||
|
||||
final class SherpaOnnxWave extends Struct {
|
||||
external Pointer<Float> samples;
|
||||
|
||||
@@ -24,17 +65,136 @@ final class SherpaOnnxSpeakerEmbeddingExtractorConfig extends Struct {
|
||||
external Pointer<Utf8> provider;
|
||||
}
|
||||
|
||||
final class SherpaOnnxCircularBuffer extends Opaque {}
|
||||
|
||||
final class SherpaOnnxVoiceActivityDetector extends Opaque {}
|
||||
|
||||
final class SherpaOnnxOnlineStream extends Opaque {}
|
||||
|
||||
final class SherpaOnnxSpeakerEmbeddingExtractor extends Opaque {}
|
||||
|
||||
final class SherpaOnnxSpeakerEmbeddingManager extends Opaque {}
|
||||
|
||||
typedef SherpaOnnxCreateVoiceActivityDetectorNative
|
||||
= Pointer<SherpaOnnxVoiceActivityDetector> Function(
|
||||
Pointer<SherpaOnnxVadModelConfig>, Float);
|
||||
|
||||
typedef SherpaOnnxCreateVoiceActivityDetector
|
||||
= Pointer<SherpaOnnxVoiceActivityDetector> Function(
|
||||
Pointer<SherpaOnnxVadModelConfig>, double);
|
||||
|
||||
typedef SherpaOnnxDestroyVoiceActivityDetectorNative = Void Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>);
|
||||
|
||||
typedef SherpaOnnxDestroyVoiceActivityDetector = void Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorAcceptWaveformNative = Void Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>, Pointer<Float>, Int32);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorAcceptWaveform = void Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>, Pointer<Float>, int);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorEmptyNative = Int32 Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorEmpty = int Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorDetectedNative = Int32 Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorDetected = int Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorPopNative = Void Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorPop = void Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorClearNative = Void Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorClear = void Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorResetNative = Void Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorReset = void Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorFrontNative
|
||||
= Pointer<SherpaOnnxSpeechSegment> Function(
|
||||
Pointer<SherpaOnnxVoiceActivityDetector>);
|
||||
|
||||
typedef SherpaOnnxVoiceActivityDetectorFront
|
||||
= SherpaOnnxVoiceActivityDetectorFrontNative;
|
||||
|
||||
typedef SherpaOnnxDestroySpeechSegmentNative = Void Function(
|
||||
Pointer<SherpaOnnxSpeechSegment>);
|
||||
|
||||
typedef SherpaOnnxDestroySpeechSegment = void Function(
|
||||
Pointer<SherpaOnnxSpeechSegment>);
|
||||
|
||||
typedef SherpaOnnxCreateCircularBufferNative = Pointer<SherpaOnnxCircularBuffer>
|
||||
Function(Int32);
|
||||
|
||||
typedef SherpaOnnxCreateCircularBuffer = Pointer<SherpaOnnxCircularBuffer>
|
||||
Function(int);
|
||||
|
||||
typedef SherpaOnnxDestroyCircularBufferNative = Void Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>);
|
||||
|
||||
typedef SherpaOnnxDestroyCircularBuffer = void Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>);
|
||||
|
||||
typedef SherpaOnnxCircularBufferPushNative = Void Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>, Pointer<Float>, Int32);
|
||||
|
||||
typedef SherpaOnnxCircularBufferPush = void Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>, Pointer<Float>, int);
|
||||
|
||||
typedef SherpaOnnxCircularBufferGetNative = Pointer<Float> Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>, Int32, Int32);
|
||||
|
||||
typedef SherpaOnnxCircularBufferGet = Pointer<Float> Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>, int, int);
|
||||
|
||||
typedef SherpaOnnxCircularBufferFreeNative = Void Function(Pointer<Float>);
|
||||
|
||||
typedef SherpaOnnxCircularBufferFree = void Function(Pointer<Float>);
|
||||
|
||||
typedef SherpaOnnxCircularBufferPopNative = Void Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>, Int32);
|
||||
|
||||
typedef SherpaOnnxCircularBufferPop = void Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>, int);
|
||||
|
||||
typedef SherpaOnnxCircularBufferSizeNative = Int32 Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>);
|
||||
|
||||
typedef SherpaOnnxCircularBufferSize = int Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>);
|
||||
|
||||
typedef SherpaOnnxCircularBufferHeadNative = Int32 Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>);
|
||||
|
||||
typedef SherpaOnnxCircularBufferHead = int Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>);
|
||||
|
||||
typedef SherpaOnnxCircularBufferResetNative = Void Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>);
|
||||
|
||||
typedef SherpaOnnxCircularBufferReset = void Function(
|
||||
Pointer<SherpaOnnxCircularBuffer>);
|
||||
|
||||
typedef SherpaOnnxCreateSpeakerEmbeddingManagerNative
|
||||
= Pointer<SherpaOnnxSpeakerEmbeddingManager> Function(Int32 dim);
|
||||
= Pointer<SherpaOnnxSpeakerEmbeddingManager> Function(Int32);
|
||||
|
||||
typedef SherpaOnnxCreateSpeakerEmbeddingManager
|
||||
= Pointer<SherpaOnnxSpeakerEmbeddingManager> Function(int dim);
|
||||
= Pointer<SherpaOnnxSpeakerEmbeddingManager> Function(int);
|
||||
|
||||
typedef SherpaOnnxDestroySpeakerEmbeddingManagerNative = Void Function(
|
||||
Pointer<SherpaOnnxSpeakerEmbeddingManager>);
|
||||
@@ -190,6 +350,45 @@ typedef SherpaOnnxFreeWaveNative = Void Function(Pointer<SherpaOnnxWave>);
|
||||
typedef SherpaOnnxFreeWave = void Function(Pointer<SherpaOnnxWave>);
|
||||
|
||||
class SherpaOnnxBindings {
|
||||
static SherpaOnnxCreateVoiceActivityDetector? createVoiceActivityDetector;
|
||||
|
||||
static SherpaOnnxDestroyVoiceActivityDetector? destroyVoiceActivityDetector;
|
||||
|
||||
static SherpaOnnxVoiceActivityDetectorAcceptWaveform?
|
||||
voiceActivityDetectorAcceptWaveform;
|
||||
|
||||
static SherpaOnnxVoiceActivityDetectorEmpty? voiceActivityDetectorEmpty;
|
||||
|
||||
static SherpaOnnxVoiceActivityDetectorDetected? voiceActivityDetectorDetected;
|
||||
|
||||
static SherpaOnnxVoiceActivityDetectorPop? voiceActivityDetectorPop;
|
||||
|
||||
static SherpaOnnxVoiceActivityDetectorClear? voiceActivityDetectorClear;
|
||||
|
||||
static SherpaOnnxVoiceActivityDetectorFront? voiceActivityDetectorFront;
|
||||
|
||||
static SherpaOnnxDestroySpeechSegment? destroySpeechSegment;
|
||||
|
||||
static SherpaOnnxVoiceActivityDetectorReset? voiceActivityDetectorReset;
|
||||
|
||||
static SherpaOnnxCreateCircularBuffer? createCircularBuffer;
|
||||
|
||||
static SherpaOnnxDestroyCircularBuffer? destroyCircularBuffer;
|
||||
|
||||
static SherpaOnnxCircularBufferPush? circularBufferPush;
|
||||
|
||||
static SherpaOnnxCircularBufferGet? circularBufferGet;
|
||||
|
||||
static SherpaOnnxCircularBufferFree? circularBufferFree;
|
||||
|
||||
static SherpaOnnxCircularBufferPop? circularBufferPop;
|
||||
|
||||
static SherpaOnnxCircularBufferSize? circularBufferSize;
|
||||
|
||||
static SherpaOnnxCircularBufferHead? circularBufferHead;
|
||||
|
||||
static SherpaOnnxCircularBufferReset? circularBufferReset;
|
||||
|
||||
static SherpaOnnxCreateSpeakerEmbeddingExtractor?
|
||||
createSpeakerEmbeddingExtractor;
|
||||
|
||||
@@ -252,8 +451,107 @@ class SherpaOnnxBindings {
|
||||
static SherpaOnnxFreeWave? freeWave;
|
||||
|
||||
static void init(DynamicLibrary dynamicLibrary) {
|
||||
createVoiceActivityDetector ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxCreateVoiceActivityDetectorNative>>(
|
||||
'SherpaOnnxCreateVoiceActivityDetector')
|
||||
.asFunction();
|
||||
|
||||
destroyVoiceActivityDetector ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxDestroyVoiceActivityDetectorNative>>(
|
||||
'SherpaOnnxDestroyVoiceActivityDetector')
|
||||
.asFunction();
|
||||
|
||||
voiceActivityDetectorAcceptWaveform ??= dynamicLibrary
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
SherpaOnnxVoiceActivityDetectorAcceptWaveformNative>>(
|
||||
'SherpaOnnxVoiceActivityDetectorAcceptWaveform')
|
||||
.asFunction();
|
||||
|
||||
voiceActivityDetectorEmpty ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxVoiceActivityDetectorEmptyNative>>(
|
||||
'SherpaOnnxVoiceActivityDetectorEmpty')
|
||||
.asFunction();
|
||||
|
||||
voiceActivityDetectorDetected ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxVoiceActivityDetectorDetectedNative>>(
|
||||
'SherpaOnnxVoiceActivityDetectorDetected')
|
||||
.asFunction();
|
||||
|
||||
voiceActivityDetectorPop ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxVoiceActivityDetectorPopNative>>(
|
||||
'SherpaOnnxVoiceActivityDetectorPop')
|
||||
.asFunction();
|
||||
|
||||
voiceActivityDetectorClear ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxVoiceActivityDetectorClearNative>>(
|
||||
'SherpaOnnxVoiceActivityDetectorClear')
|
||||
.asFunction();
|
||||
|
||||
voiceActivityDetectorFront ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxVoiceActivityDetectorFrontNative>>(
|
||||
'SherpaOnnxVoiceActivityDetectorFront')
|
||||
.asFunction();
|
||||
|
||||
destroySpeechSegment ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxDestroySpeechSegmentNative>>(
|
||||
'SherpaOnnxDestroySpeechSegment')
|
||||
.asFunction();
|
||||
|
||||
voiceActivityDetectorReset ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxVoiceActivityDetectorResetNative>>(
|
||||
'SherpaOnnxVoiceActivityDetectorReset')
|
||||
.asFunction();
|
||||
|
||||
createCircularBuffer ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxCreateCircularBufferNative>>(
|
||||
'SherpaOnnxCreateCircularBuffer')
|
||||
.asFunction();
|
||||
|
||||
destroyCircularBuffer ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxDestroyCircularBufferNative>>(
|
||||
'SherpaOnnxDestroyCircularBuffer')
|
||||
.asFunction();
|
||||
|
||||
circularBufferPush ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxCircularBufferPushNative>>(
|
||||
'SherpaOnnxCircularBufferPush')
|
||||
.asFunction();
|
||||
|
||||
circularBufferGet ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxCircularBufferGetNative>>(
|
||||
'SherpaOnnxCircularBufferGet')
|
||||
.asFunction();
|
||||
|
||||
circularBufferFree ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxCircularBufferFreeNative>>(
|
||||
'SherpaOnnxCircularBufferFree')
|
||||
.asFunction();
|
||||
|
||||
circularBufferPop ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxCircularBufferPopNative>>(
|
||||
'SherpaOnnxCircularBufferPop')
|
||||
.asFunction();
|
||||
|
||||
circularBufferSize ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxCircularBufferSizeNative>>(
|
||||
'SherpaOnnxCircularBufferSize')
|
||||
.asFunction();
|
||||
|
||||
circularBufferHead ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxCircularBufferHeadNative>>(
|
||||
'SherpaOnnxCircularBufferHead')
|
||||
.asFunction();
|
||||
|
||||
circularBufferReset ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxCircularBufferResetNative>>(
|
||||
'SherpaOnnxCircularBufferReset')
|
||||
.asFunction();
|
||||
|
||||
createSpeakerEmbeddingExtractor ??= dynamicLibrary
|
||||
.lookup<NativeFunction<SherpaOnnxCreateSpeakerEmbeddingExtractor>>(
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
SherpaOnnxCreateSpeakerEmbeddingExtractorNative>>(
|
||||
'SherpaOnnxCreateSpeakerEmbeddingExtractor')
|
||||
.asFunction();
|
||||
|
||||
|
||||
@@ -2,19 +2,20 @@
|
||||
import 'dart:ffi';
|
||||
import 'dart:typed_data';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import "./sherpa_onnx_bindings.dart";
|
||||
import "./online_stream.dart";
|
||||
|
||||
import './online_stream.dart';
|
||||
import './sherpa_onnx_bindings.dart';
|
||||
|
||||
class SpeakerEmbeddingExtractorConfig {
|
||||
const SpeakerEmbeddingExtractorConfig(
|
||||
{required this.model,
|
||||
this.numThreads = 1,
|
||||
this.debug = true,
|
||||
this.provider = "cpu"});
|
||||
this.provider = 'cpu'});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "SpeakerEmbeddingExtractorConfig(model: $model, numThreads: $numThreads, debug: $debug, provider: $provider)";
|
||||
return 'SpeakerEmbeddingExtractorConfig(model: $model, numThreads: $numThreads, debug: $debug, provider: $provider)';
|
||||
}
|
||||
|
||||
final String model;
|
||||
@@ -116,7 +117,7 @@ class SpeakerEmbeddingManager {
|
||||
|
||||
/// 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}");
|
||||
assert(embedding.length == this.dim, '${embedding.length} vs ${this.dim}');
|
||||
|
||||
final Pointer<Utf8> namePtr = name.toNativeUtf8();
|
||||
final int n = embedding.length;
|
||||
@@ -145,7 +146,7 @@ class SpeakerEmbeddingManager {
|
||||
|
||||
int offset = 0;
|
||||
for (final e in embeddingList) {
|
||||
assert(e.length == this.dim, "${e.length} vs ${this.dim}");
|
||||
assert(e.length == this.dim, '${e.length} vs ${this.dim}');
|
||||
|
||||
pList.setAll(offset, e);
|
||||
offset += this.dim;
|
||||
|
||||
213
sherpa-onnx/flutter/lib/src/vad.dart
Normal file
213
sherpa-onnx/flutter/lib/src/vad.dart
Normal file
@@ -0,0 +1,213 @@
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
import 'dart:ffi';
|
||||
import 'dart:typed_data';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
import './sherpa_onnx_bindings.dart';
|
||||
|
||||
class SileroVadModelConfig {
|
||||
const SileroVadModelConfig(
|
||||
{this.model = '',
|
||||
this.threshold = 0.5,
|
||||
this.minSilenceDuration = 0.5,
|
||||
this.minSpeechDuration = 0.25,
|
||||
this.windowSize = 512});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SileroVadModelConfig(model: $model, threshold: $threshold, minSilenceDuration: $minSilenceDuration, minSpeechDuration: $minSpeechDuration, windowSize: $windowSize)';
|
||||
}
|
||||
|
||||
final String model;
|
||||
final double threshold;
|
||||
final double minSilenceDuration;
|
||||
final double minSpeechDuration;
|
||||
final int windowSize;
|
||||
}
|
||||
|
||||
class VadModelConfig {
|
||||
VadModelConfig(
|
||||
{this.sileroVad = const SileroVadModelConfig(),
|
||||
this.sampleRate = 16000,
|
||||
this.numThreads = 1,
|
||||
this.provider = 'cpu',
|
||||
this.debug = true});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'VadModelConfig(sileroVad: $sileroVad, sampleRate: $sampleRate, numThreads: $numThreads, provider: $provider, debug: $debug)';
|
||||
}
|
||||
|
||||
final SileroVadModelConfig sileroVad;
|
||||
final int sampleRate;
|
||||
final int numThreads;
|
||||
final String provider;
|
||||
final bool debug;
|
||||
}
|
||||
|
||||
class SpeechSegment {
|
||||
SpeechSegment({required this.samples, required this.start});
|
||||
final Float32List samples;
|
||||
final int start;
|
||||
}
|
||||
|
||||
class CircularBuffer {
|
||||
CircularBuffer._({required this.ptr});
|
||||
|
||||
/// The user has to invoke CircularBuffer.free() on the returned instance
|
||||
/// to avoid memory leak.
|
||||
factory CircularBuffer({required int capacity}) {
|
||||
assert(capacity > 0, 'capacity is $capacity');
|
||||
final p =
|
||||
SherpaOnnxBindings.createCircularBuffer?.call(capacity) ?? nullptr;
|
||||
|
||||
return CircularBuffer._(ptr: p);
|
||||
}
|
||||
|
||||
void free() {
|
||||
SherpaOnnxBindings.destroyCircularBuffer?.call(ptr);
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
void push(Float32List data) {
|
||||
final n = data.length;
|
||||
final Pointer<Float> p = calloc<Float>(n);
|
||||
|
||||
final pList = p.asTypedList(n);
|
||||
pList.setAll(0, data);
|
||||
|
||||
SherpaOnnxBindings.circularBufferPush?.call(this.ptr, p, n);
|
||||
|
||||
calloc.free(p);
|
||||
}
|
||||
|
||||
Float32List get({required int startIndex, required int n}) {
|
||||
final Pointer<Float> p =
|
||||
SherpaOnnxBindings.circularBufferGet?.call(this.ptr, startIndex, n) ??
|
||||
nullptr;
|
||||
|
||||
if (p == nullptr) {
|
||||
return Float32List(0);
|
||||
}
|
||||
|
||||
final pList = p.asTypedList(n);
|
||||
final Float32List ans = Float32List.fromList(pList);
|
||||
|
||||
SherpaOnnxBindings.circularBufferFree?.call(p);
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
void pop(int n) {
|
||||
SherpaOnnxBindings.circularBufferPop?.call(this.ptr, n);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
SherpaOnnxBindings.circularBufferReset?.call(this.ptr);
|
||||
}
|
||||
|
||||
int get size => SherpaOnnxBindings.circularBufferSize?.call(this.ptr) ?? 0;
|
||||
int get head => SherpaOnnxBindings.circularBufferHead?.call(this.ptr) ?? 0;
|
||||
|
||||
Pointer<SherpaOnnxCircularBuffer> ptr;
|
||||
}
|
||||
|
||||
class VoiceActivityDetector {
|
||||
VoiceActivityDetector._({required this.ptr});
|
||||
|
||||
// The user has to invoke VoiceActivityDetector.free() to avoid memory leak.
|
||||
factory VoiceActivityDetector(
|
||||
{required VadModelConfig config, required double bufferSizeInSeconds}) {
|
||||
final c = calloc<SherpaOnnxVadModelConfig>();
|
||||
|
||||
final modelPtr = config.sileroVad.model.toNativeUtf8();
|
||||
c.ref.sileroVad.model = modelPtr;
|
||||
|
||||
c.ref.sileroVad.threshold = config.sileroVad.threshold;
|
||||
c.ref.sileroVad.minSilenceDuration = config.sileroVad.minSilenceDuration;
|
||||
c.ref.sileroVad.minSpeechDuration = config.sileroVad.minSpeechDuration;
|
||||
c.ref.sileroVad.windowSize = config.sileroVad.windowSize;
|
||||
|
||||
c.ref.sampleRate = config.sampleRate;
|
||||
c.ref.numThreads = config.numThreads;
|
||||
|
||||
final providerPtr = config.provider.toNativeUtf8();
|
||||
c.ref.provider = providerPtr;
|
||||
|
||||
c.ref.debug = config.debug ? 1 : 0;
|
||||
|
||||
final ptr = SherpaOnnxBindings.createVoiceActivityDetector
|
||||
?.call(c, bufferSizeInSeconds) ??
|
||||
nullptr;
|
||||
|
||||
calloc.free(providerPtr);
|
||||
calloc.free(modelPtr);
|
||||
calloc.free(c);
|
||||
|
||||
return VoiceActivityDetector._(ptr: ptr);
|
||||
}
|
||||
|
||||
void free() {
|
||||
SherpaOnnxBindings.destroyVoiceActivityDetector?.call(ptr);
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
void acceptWaveform(Float32List samples) {
|
||||
final n = samples.length;
|
||||
final Pointer<Float> p = calloc<Float>(n);
|
||||
|
||||
final pList = p.asTypedList(n);
|
||||
pList.setAll(0, samples);
|
||||
|
||||
SherpaOnnxBindings.voiceActivityDetectorAcceptWaveform
|
||||
?.call(this.ptr, p, n);
|
||||
|
||||
calloc.free(p);
|
||||
}
|
||||
|
||||
bool isEmpty() {
|
||||
final int empty =
|
||||
SherpaOnnxBindings.voiceActivityDetectorEmpty?.call(this.ptr) ?? 0;
|
||||
|
||||
return empty == 1;
|
||||
}
|
||||
|
||||
bool isDetected() {
|
||||
final int detected =
|
||||
SherpaOnnxBindings.voiceActivityDetectorDetected?.call(this.ptr) ?? 0;
|
||||
|
||||
return detected == 1;
|
||||
}
|
||||
|
||||
void pop() {
|
||||
SherpaOnnxBindings.voiceActivityDetectorPop?.call(this.ptr);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
SherpaOnnxBindings.voiceActivityDetectorClear?.call(this.ptr);
|
||||
}
|
||||
|
||||
SpeechSegment front() {
|
||||
final Pointer<SherpaOnnxSpeechSegment> segment =
|
||||
SherpaOnnxBindings.voiceActivityDetectorFront?.call(this.ptr) ??
|
||||
nullptr;
|
||||
if (segment == nullptr) {
|
||||
return SpeechSegment(samples: Float32List(0), start: 0);
|
||||
}
|
||||
|
||||
final sampleList = segment.ref.samples.asTypedList(segment.ref.n);
|
||||
final start = segment.ref.start;
|
||||
|
||||
final samples = Float32List.fromList(sampleList);
|
||||
|
||||
SherpaOnnxBindings.destroySpeechSegment?.call(segment);
|
||||
|
||||
return SpeechSegment(samples: samples, start: start);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
SherpaOnnxBindings.voiceActivityDetectorReset?.call(this.ptr);
|
||||
}
|
||||
|
||||
Pointer<SherpaOnnxVoiceActivityDetector> ptr;
|
||||
}
|
||||
@@ -2,7 +2,8 @@
|
||||
import 'dart:ffi';
|
||||
import 'dart:typed_data';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import "./sherpa_onnx_bindings.dart";
|
||||
|
||||
import './sherpa_onnx_bindings.dart';
|
||||
|
||||
class WaveData {
|
||||
WaveData({required this.samples, required this.sampleRate});
|
||||
|
||||
Reference in New Issue
Block a user