1717#include < string>
1818#include < utility>
1919#include < vector>
20+ #ifndef M_PI
21+ #define M_PI 3.14159265358979323846 // not guaranteed by <cmath> on MSVC
22+ #endif
2023
2124namespace funasr_vad_impl {
2225static const int FS =16000 ,WINLEN =400 ,SHIFT =160 ,NFFT =512 ,NMEL =80 ;
@@ -40,7 +43,8 @@ static std::vector<std::vector<float>> fbank80(std::vector<float> wav){
4043 return feat;
4144}
4245static std::vector<float > lfr (const std::vector<std::vector<float >>&feat,int m,int n,int &T_out){
43- int T=feat.size (),D=NMEL ,pad=(m-1 )/2 ; int Tl=T>0 ?(T+n-1 )/n:0 ;
46+ int T=feat.size (); if (T<1 ){T_out=0 ;return {};} // empty (audio shorter than one frame)
47+ int D=NMEL ,pad=(m-1 )/2 ; int Tl=(T+n-1 )/n;
4448 std::vector<std::vector<float >> pf; pf.reserve (T+pad+m);
4549 for (int i=0 ;i<pad;i++)pf.push_back (feat[0 ]);
4650 for (int t=0 ;t<T;t++)pf.push_back (feat[t]);
@@ -68,20 +72,32 @@ inline bool funasr_vad_segments(const std::string& gguf_path, const std::vector<
6872 for (int i=0 ;i<gguf_get_n_tensors (gg);i++){const char *nm=gguf_get_tensor_name (gg,i);m.t [nm]=ggml_get_tensor (m.ctx ,nm);}
6973 gguf_free (gg);
7074
75+ // fail fast (not segfault) if the GGUF is missing tensors the graph dereferences
76+ auto need=[&](const std::string&n){ return m.g (n)!=nullptr ; };
77+ bool ok_t = need (" cmvn.shift" )&&need (" cmvn.scale" )&&need (" encoder.in_linear1.linear.weight" )
78+ &&need (" encoder.in_linear2.linear.weight" )&&need (" encoder.out_linear1.linear.weight" )
79+ &&need (" encoder.out_linear2.linear.weight" );
80+ for (int i=0 ;i<nl&&ok_t ;i++){std::string p=" encoder.fsmn." +std::to_string (i)+" ." ;
81+ ok_t =need (p+" linear.linear.weight" )&&need (p+" fsmn_block.conv_left.weight" )&&need (p+" affine.linear.weight" );}
82+ if (!ok_t ){fprintf (stderr," vad: gguf missing required tensors\n " ); if (m.ctx )ggml_free (m.ctx ); return false ;}
83+
7184 auto feat=fbank80 (wav); int T=0 ; auto feats=lfr (feat,lm,ln,T); // [T,400]
7285 if (T<1 ){if (m.ctx )ggml_free (m.ctx );return true ;} // too short -> no speech
7386 float *shift=(float *)m.g (" cmvn.shift" )->data ,*scale=(float *)m.g (" cmvn.scale" )->data ;
7487 for (int t=0 ;t<T;t++)for (int d=0 ;d<idim;d++)feats[(size_t )t*idim+d]=(feats[(size_t )t*idim+d]+shift[d])*scale[d];
7588
7689 ggml_backend_t be=ggml_backend_cpu_init ();
77- ggml_init_params cp={(size_t )512 *1024 *1024 ,nullptr ,true }; ggml_context*c=ggml_init (cp);
90+ // no_alloc=true -> ctx holds only tensor/graph metadata (the real compute buffer is
91+ // allocated by gallocr below), so a few MB is plenty regardless of clip length.
92+ ggml_init_params cp={(size_t )16 *1024 *1024 ,nullptr ,true }; ggml_context*c=ggml_init (cp);
7893 ggml_tensor*x=ggml_new_tensor_2d (c,GGML_TYPE_F32 ,idim,T); ggml_set_input (x);
7994 ggml_tensor*h=lin (c,m.g (" encoder.in_linear1.linear.weight" ),m.g (" encoder.in_linear1.linear.bias" ),x);
8095 h=lin (c,m.g (" encoder.in_linear2.linear.weight" ),m.g (" encoder.in_linear2.linear.bias" ),h); h=ggml_relu (c,h);
8196 for (int i=0 ;i<nl;i++){std::string p=" encoder.fsmn." +std::to_string (i)+" ." ;
8297 ggml_tensor*z=ggml_mul_mat (c,m.g (p+" linear.linear.weight" ),h);
8398 ggml_tensor*fk=m.g (p+" fsmn_block.conv_left.weight" ); ggml_tensor*zp=ggml_pad_ext (c,z,0 ,0 ,lorder-1 ,0 ,0 ,0 ,0 ,0 ); ggml_tensor*acc=z;
84- for (int j=0 ;j<lorder;j++){auto sl=ggml_view_2d (c,zp,pd,T,zp->nb [1 ],(size_t )j*zp->nb [1 ]);auto wj=ggml_view_1d (c,fk,pd,(size_t )j*fk->nb [1 ]);acc=ggml_add (c,acc,ggml_mul (c,ggml_cont (c,sl),wj));}
99+ // sl is a full-row slice of the contiguous padded tensor -> already contiguous, no ggml_cont needed
100+ for (int j=0 ;j<lorder;j++){auto sl=ggml_view_2d (c,zp,pd,T,zp->nb [1 ],(size_t )j*zp->nb [1 ]);auto wj=ggml_view_1d (c,fk,pd,(size_t )j*fk->nb [1 ]);acc=ggml_add (c,acc,ggml_mul (c,sl,wj));}
85101 ggml_tensor*a=lin (c,m.g (p+" affine.linear.weight" ),m.g (p+" affine.linear.bias" ),acc); h=ggml_relu (c,a);}
86102 h=lin (c,m.g (" encoder.out_linear1.linear.weight" ),m.g (" encoder.out_linear1.linear.bias" ),h);
87103 h=lin (c,m.g (" encoder.out_linear2.linear.weight" ),m.g (" encoder.out_linear2.linear.bias" ),h);
0 commit comments