@@ -217,6 +217,17 @@ class DiarizeSegment {
217217 DiarizeSegment ({required this .t0, required this .t1, this .speaker = - 1 });
218218}
219219
220+ /// One audio-derived speaker turn returned by FoxNose.
221+ ///
222+ /// Times are seconds on the same absolute timeline as [DiarizeSegment] .
223+ class DiarizeTurn {
224+ final double t0;
225+ final double t1;
226+ final int speaker;
227+ const DiarizeTurn (
228+ {required this .t0, required this .t1, required this .speaker});
229+ }
230+
220231enum DiarizeMethod {
221232 /// Stereo only. |L| vs |R| energy per segment, 1.1× margin.
222233 energy,
@@ -258,6 +269,10 @@ enum DiarizeMethod {
258269/// WeSpeaker embedder GGUF; [minSpeakers] / [maxSpeakers] bound the
259270/// automatic speaker-count estimation (0 keeps the library defaults 1 / 8)
260271/// and [numSpeakers] > 0 pins the count and skips estimation.
272+ ///
273+ /// When [outTurns] is supplied, the function calls the CrispASR 0.8.30+
274+ /// turn-returning ABI and replaces that list with FoxNose's audio-derived
275+ /// turns. Other methods leave it empty.
261276bool diarizeSegments ({
262277 required List <DiarizeSegment > segs,
263278 required Float32List left,
@@ -271,8 +286,10 @@ bool diarizeSegments({
271286 int minSpeakers = 0 ,
272287 int maxSpeakers = 0 ,
273288 int numSpeakers = 0 ,
289+ List <DiarizeTurn >? outTurns,
274290 DynamicLibrary ? lib,
275291}) {
292+ outTurns? .clear ();
276293 if (segs.isEmpty || left.isEmpty) return true ;
277294 lib ?? = DynamicLibrary .open (CrispASR .defaultLibName ());
278295
@@ -329,13 +346,68 @@ bool diarizeSegments({
329346 (optsPtr + 40 ).cast <Int32 >().value = numSpeakers;
330347 (optsPtr + 44 ).cast <Int32 >().value = 0 ;
331348
332- final fn = lib.lookupFunction<
333- Int32 Function (Pointer <Float >, Pointer <Float >, Int32 , Int32 ,
334- Pointer <Uint8 >, Int32 , Pointer <Uint8 >),
335- int Function (Pointer <Float >, Pointer <Float >, int , int , Pointer <Uint8 >,
336- int , Pointer <Uint8 >)> ('crispasr_diarize_segments_abi' );
337- final rc =
338- fn (leftPtr, rightPtr, n, isStereo ? 1 : 0 , segsPtr, segs.length, optsPtr);
349+ var rc = 0 ;
350+ if (outTurns == null ) {
351+ final fn = lib.lookupFunction<
352+ Int32 Function (Pointer <Float >, Pointer <Float >, Int32 , Int32 ,
353+ Pointer <Uint8 >, Int32 , Pointer <Uint8 >),
354+ int Function (Pointer <Float >, Pointer <Float >, int , int , Pointer <Uint8 >,
355+ int , Pointer <Uint8 >)> ('crispasr_diarize_segments_abi' );
356+ rc = fn (
357+ leftPtr, rightPtr, n, isStereo ? 1 : 0 , segsPtr, segs.length, optsPtr);
358+ } else {
359+ final fn = lib.lookupFunction<
360+ Int32 Function (
361+ Pointer <Float >,
362+ Pointer <Float >,
363+ Int32 ,
364+ Int32 ,
365+ Pointer <Uint8 >,
366+ Int32 ,
367+ Pointer <Uint8 >,
368+ Pointer <Uint8 >,
369+ Int32 ,
370+ Pointer <Int32 >),
371+ int Function (
372+ Pointer <Float >,
373+ Pointer <Float >,
374+ int ,
375+ int ,
376+ Pointer <Uint8 >,
377+ int ,
378+ Pointer <Uint8 >,
379+ Pointer <Uint8 >,
380+ int ,
381+ Pointer <Int32 >)> ('crispasr_diarize_segments_turns_abi' );
382+ var turnCap = ((n + 7999 ) ~ / 8000 ) + segs.length + 16 ;
383+ for (var attempt = 0 ; attempt < 2 ; attempt++ ) {
384+ final turnsPtr = calloc <Uint8 >(turnCap * 24 );
385+ final nTurnsPtr = calloc <Int32 >();
386+ rc = fn (leftPtr, rightPtr, n, isStereo ? 1 : 0 , segsPtr, segs.length,
387+ optsPtr, turnsPtr, turnCap, nTurnsPtr);
388+ final required = nTurnsPtr.value;
389+ if (rc == 2 && attempt == 0 && required > turnCap) {
390+ calloc.free (turnsPtr);
391+ calloc.free (nTurnsPtr);
392+ turnCap = required ;
393+ continue ;
394+ }
395+ if (rc == 0 ) {
396+ final count = required < turnCap ? required : turnCap;
397+ for (var i = 0 ; i < count; i++ ) {
398+ final base = turnsPtr + i * 24 ;
399+ outTurns.add (DiarizeTurn (
400+ t0: base .cast <Int64 >().value / 100.0 ,
401+ t1: (base + 8 ).cast <Int64 >().value / 100.0 ,
402+ speaker: (base + 16 ).cast <Int32 >().value,
403+ ));
404+ }
405+ }
406+ calloc.free (turnsPtr);
407+ calloc.free (nTurnsPtr);
408+ break ;
409+ }
410+ }
339411
340412 if (rc == 0 ) {
341413 for (var i = 0 ; i < segs.length; i++ ) {
0 commit comments