@@ -53,6 +53,9 @@ static ID id_pre_converted_models;
5353
5454static  bool  is_log_callback_finalized = false ;
5555
56+ //  High level API
57+ static  VALUE rb_whisper_segment_initialize (VALUE context, int  index);
58+ 
5659/* 
5760 * call-seq: 
5861 *   lang_max_id -> Integer 
@@ -187,6 +190,69 @@ static ruby_whisper_callback_container * rb_whisper_callback_container_allocate(
187190  return  container;
188191}
189192
193+ static  void  new_segment_callback (struct  whisper_context  *ctx, struct  whisper_state  *state, int  n_new, void  *user_data) {
194+   const  ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data;
195+ 
196+   //  Currently, doesn't support state because
197+   //  those require to resolve GC-related problems.
198+   if  (!NIL_P (container->callback )) {
199+     rb_funcall (container->callback , id_call, 4 , *container->context , Qnil, INT2NUM (n_new), container->user_data );
200+   }
201+   const  long  callbacks_len = RARRAY_LEN (container->callbacks );
202+   if  (0  == callbacks_len) {
203+     return ;
204+   }
205+   const  int  n_segments = whisper_full_n_segments_from_state (state);
206+   for  (int  i = n_new; i > 0 ; i--) {
207+     int  i_segment = n_segments - i;
208+     VALUE segment = rb_whisper_segment_initialize (*container->context , i_segment);
209+     for  (int  j = 0 ; j < callbacks_len; j++) {
210+       VALUE cb = rb_ary_entry (container->callbacks , j);
211+       rb_funcall (cb, id_call, 1 , segment);
212+     }
213+   }
214+ }
215+ 
216+ static  void  progress_callback (struct  whisper_context  *ctx, struct  whisper_state  *state, int  progress_cur, void  *user_data) {
217+   const  ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data;
218+   const  VALUE progress = INT2NUM (progress_cur);
219+   //  Currently, doesn't support state because
220+   //  those require to resolve GC-related problems.
221+   if  (!NIL_P (container->callback )) {
222+     rb_funcall (container->callback , id_call, 4 , *container->context , Qnil, progress, container->user_data );
223+   }
224+   const  long  callbacks_len = RARRAY_LEN (container->callbacks );
225+   if  (0  == callbacks_len) {
226+     return ;
227+   }
228+   for  (int  j = 0 ; j < callbacks_len; j++) {
229+     VALUE cb = rb_ary_entry (container->callbacks , j);
230+     rb_funcall (cb, id_call, 1 , progress);
231+   }
232+ }
233+ 
234+ static  bool  abort_callback (void  * user_data) {
235+   const  ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data;
236+   if  (!NIL_P (container->callback )) {
237+     VALUE result = rb_funcall (container->callback , id_call, 1 , container->user_data );
238+     if  (!NIL_P (result) && Qfalse != result) {
239+       return  true ;
240+     }
241+   }
242+   const  long  callbacks_len = RARRAY_LEN (container->callbacks );
243+   if  (0  == callbacks_len) {
244+     return  false ;
245+   }
246+   for  (int  j = 0 ; j < callbacks_len; j++) {
247+     VALUE cb = rb_ary_entry (container->callbacks , j);
248+     VALUE result = rb_funcall (cb, id_call, 1 , container->user_data );
249+     if  (!NIL_P (result) && Qfalse != result) {
250+       return  true ;
251+     }
252+   }
253+   return  false ;
254+ }
255+ 
190256static  VALUE ruby_whisper_params_allocate (VALUE klass) {
191257  ruby_whisper_params *rwp;
192258  rwp = ALLOC (ruby_whisper_params);
@@ -230,8 +296,25 @@ static VALUE ruby_whisper_initialize(int argc, VALUE *argv, VALUE self) {
230296  return  self;
231297}
232298
233- //  High level API
234- static  VALUE rb_whisper_segment_initialize (VALUE context, int  index);
299+ static  void  register_callbacks (ruby_whisper_params * rwp, VALUE * self) {
300+   if  (!NIL_P (rwp->new_segment_callback_container ->callback ) || 0  != RARRAY_LEN (rwp->new_segment_callback_container ->callbacks )) {
301+     rwp->new_segment_callback_container ->context  = self;
302+     rwp->params .new_segment_callback  = new_segment_callback;
303+     rwp->params .new_segment_callback_user_data  = rwp->new_segment_callback_container ;
304+   }
305+ 
306+   if  (!NIL_P (rwp->progress_callback_container ->callback ) || 0  != RARRAY_LEN (rwp->progress_callback_container ->callbacks )) {
307+     rwp->progress_callback_container ->context  = self;
308+     rwp->params .progress_callback  = progress_callback;
309+     rwp->params .progress_callback_user_data  = rwp->progress_callback_container ;
310+   }
311+ 
312+   if  (!NIL_P (rwp->abort_callback_container ->callback ) || 0  != RARRAY_LEN (rwp->abort_callback_container ->callbacks )) {
313+     rwp->abort_callback_container ->context  = self;
314+     rwp->params .abort_callback  = abort_callback;
315+     rwp->params .abort_callback_user_data  = rwp->abort_callback_container ;
316+   }
317+ }
235318
236319/* 
237320 * transcribe a single file 
@@ -353,80 +436,7 @@ static VALUE ruby_whisper_transcribe(int argc, VALUE *argv, VALUE self) {
353436    rwp->params .encoder_begin_callback_user_data  = &is_aborted;
354437  }
355438
356-   if  (!NIL_P (rwp->new_segment_callback_container ->callback ) || 0  != RARRAY_LEN (rwp->new_segment_callback_container ->callbacks )) {
357-     rwp->params .new_segment_callback  = [](struct  whisper_context  * ctx, struct  whisper_state  * state, int  n_new, void  * user_data) {
358-       const  ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data;
359- 
360-       //  Currently, doesn't support state because
361-       //  those require to resolve GC-related problems.
362-       if  (!NIL_P (container->callback )) {
363-         rb_funcall (container->callback , id_call, 4 , *container->context , Qnil, INT2NUM (n_new), container->user_data );
364-       }
365-       const  long  callbacks_len = RARRAY_LEN (container->callbacks );
366-       if  (0  == callbacks_len) {
367-         return ;
368-       }
369-       const  int  n_segments = whisper_full_n_segments_from_state (state);
370-       for  (int  i = n_new; i > 0 ; i--) {
371-         int  i_segment = n_segments - i;
372-         VALUE segment = rb_whisper_segment_initialize (*container->context , i_segment);
373-         for  (int  j = 0 ; j < callbacks_len; j++) {
374-           VALUE cb = rb_ary_entry (container->callbacks , j);
375-           rb_funcall (cb, id_call, 1 , segment);
376-         }
377-       }
378-     };
379-     rwp->new_segment_callback_container ->context  = &self;
380-     rwp->params .new_segment_callback_user_data  = rwp->new_segment_callback_container ;
381-   }
382- 
383-   if  (!NIL_P (rwp->progress_callback_container ->callback ) || 0  != RARRAY_LEN (rwp->progress_callback_container ->callbacks )) {
384-     rwp->params .progress_callback  = [](struct  whisper_context  *ctx, struct  whisper_state  * /* state*/ int  progress_cur, void  *user_data) {
385-       const  ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data;
386-       const  VALUE progress = INT2NUM (progress_cur);
387-       //  Currently, doesn't support state because
388-       //  those require to resolve GC-related problems.
389-       if  (!NIL_P (container->callback )) {
390-         rb_funcall (container->callback , id_call, 4 , *container->context , Qnil, progress, container->user_data );
391-       }
392-       const  long  callbacks_len = RARRAY_LEN (container->callbacks );
393-       if  (0  == callbacks_len) {
394-         return ;
395-       }
396-       for  (int  j = 0 ; j < callbacks_len; j++) {
397-         VALUE cb = rb_ary_entry (container->callbacks , j);
398-         rb_funcall (cb, id_call, 1 , progress);
399-       }
400-     };
401-     rwp->progress_callback_container ->context  = &self;
402-     rwp->params .progress_callback_user_data  = rwp->progress_callback_container ;
403-   }
404- 
405-   if  (!NIL_P (rwp->abort_callback_container ->callback ) || 0  != RARRAY_LEN (rwp->abort_callback_container ->callbacks )) {
406-     rwp->params .abort_callback  = [](void  * user_data) {
407-       const  ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data;
408-       if  (!NIL_P (container->callback )) {
409-         VALUE result = rb_funcall (container->callback , id_call, 1 , container->user_data );
410-         if  (!NIL_P (result) && Qfalse != result) {
411-           return  true ;
412-         }
413-       }
414-       const  long  callbacks_len = RARRAY_LEN (container->callbacks );
415-       if  (0  == callbacks_len) {
416-         return  false ;
417-       }
418-       for  (int  j = 0 ; j < callbacks_len; j++) {
419-         VALUE cb = rb_ary_entry (container->callbacks , j);
420-         VALUE result = rb_funcall (cb, id_call, 1 , container->user_data );
421-         if  (!NIL_P (result) && Qfalse != result) {
422-           return  true ;
423-         }
424-       }
425-       return  false ;
426-     };
427-     rwp->abort_callback_container ->context  = &self;
428-     rwp->params .abort_callback_user_data  = rwp->abort_callback_container ;
429-   }
439+   register_callbacks (rwp, &self);
430440
431441  if  (whisper_full_parallel (rw->context , rwp->params , pcmf32.data (), pcmf32.size (), 1 ) != 0 ) {
432442    fprintf (stderr, " failed to process audio\n " 
@@ -631,6 +641,7 @@ VALUE ruby_whisper_full(int argc, VALUE *argv, VALUE self) {
631641      }
632642    }
633643  }
644+   register_callbacks (rwp, &self);
634645  const  int  result = whisper_full (rw->context , rwp->params , c_samples, n_samples);
635646  if  (0  == result) {
636647    return  Qnil;
@@ -719,6 +730,7 @@ static VALUE ruby_whisper_full_parallel(int argc, VALUE *argv,VALUE self) {
719730      }
720731    }
721732  }
733+   register_callbacks (rwp, &self);
722734  const  int  result = whisper_full_parallel (rw->context , rwp->params , c_samples, n_samples, n_processors);
723735  if  (0  == result) {
724736    return  Qnil;
@@ -823,6 +835,18 @@ static VALUE ruby_whisper_full_get_segment_text(VALUE self, VALUE i_segment) {
823835  return  rb_str_new2 (text);
824836}
825837
838+ /* 
839+  * call-seq: 
840+  *   full_get_segment_no_speech_prob -> Float 
841+  */  
842+ static  VALUE ruby_whisper_full_get_segment_no_speech_prob (VALUE self, VALUE i_segment) {
843+   ruby_whisper *rw;
844+   Data_Get_Struct (self, ruby_whisper, rw);
845+   const  int  c_i_segment = ruby_whisper_full_check_segment_index (rw, i_segment);
846+   const  float  no_speech_prob = whisper_full_get_segment_no_speech_prob (rw->context , c_i_segment);
847+   return  DBL2NUM (no_speech_prob);
848+ }
849+ 
826850/* 
827851 * params.language = "auto" | "en", etc... 
828852 * 
@@ -1547,6 +1571,18 @@ static VALUE ruby_whisper_segment_get_text(VALUE self) {
15471571  return  rb_str_new2 (text);
15481572}
15491573
1574+ /* 
1575+  * call-seq: 
1576+  *   no_speech_prob -> Float 
1577+  */  
1578+ static  VALUE ruby_whisper_segment_get_no_speech_prob (VALUE self) {
1579+   ruby_whisper_segment *rws;
1580+   Data_Get_Struct (self, ruby_whisper_segment, rws);
1581+   ruby_whisper *rw;
1582+   Data_Get_Struct (rws->context , ruby_whisper, rw);
1583+   return  DBL2NUM (whisper_full_get_segment_no_speech_prob (rw->context , rws->index ));
1584+ }
1585+ 
15501586static  void  rb_whisper_model_mark (ruby_whisper_model *rwm) {
15511587  rb_gc_mark (rwm->context );
15521588}
@@ -1809,6 +1845,7 @@ void Init_whisper() {
18091845  rb_define_method (cContext, " full_get_segment_t1" 1 );
18101846  rb_define_method (cContext, " full_get_segment_speaker_turn_next" 1 );
18111847  rb_define_method (cContext, " full_get_segment_text" 1 );
1848+   rb_define_method (cContext, " full_get_segment_no_speech_prob" 1 );
18121849  rb_define_method (cContext, " full" 1 );
18131850  rb_define_method (cContext, " full_parallel" 1 );
18141851
@@ -1887,6 +1924,7 @@ void Init_whisper() {
18871924  rb_define_method (cSegment, " end_time" 0 );
18881925  rb_define_method (cSegment, " speaker_next_turn?" 0 );
18891926  rb_define_method (cSegment, " text" 0 );
1927+   rb_define_method (cSegment, " no_speech_prob" 0 );
18901928
18911929  cModel = rb_define_class_under (mWhisper , " Model" 
18921930  rb_define_alloc_func (cModel, ruby_whisper_model_allocate);
0 commit comments