|
|
|
|
@ -13,6 +13,9 @@
|
|
|
|
|
|
|
|
|
|
/* Число float-элементов рекуррентного состояния модели: 2 * 1 * 128 */ |
|
|
|
|
#define SILERO_VAD_STATE_COUNT 256 |
|
|
|
|
/* ONNX-вход: 64 отсчёта предыдущего окна + 512 новых отсчётов @16кГц. */ |
|
|
|
|
#define SILERO_VAD_CONTEXT_SAMPLES 64 |
|
|
|
|
#define SILERO_VAD_INPUT_SAMPLES (SILERO_VAD_CONTEXT_SAMPLES + SILERO_VAD_WINDOW_SAMPLES) |
|
|
|
|
|
|
|
|
|
struct silero_vad { |
|
|
|
|
const OrtApi* ort; |
|
|
|
|
@ -20,6 +23,7 @@ struct silero_vad {
|
|
|
|
|
OrtSession* session; |
|
|
|
|
OrtMemoryInfo* mem_info; |
|
|
|
|
float state[SILERO_VAD_STATE_COUNT]; /* рекуррентное состояние между вызовами */ |
|
|
|
|
float context[SILERO_VAD_CONTEXT_SAMPLES]; /* звуковой контекст предыдущего окна */ |
|
|
|
|
uint8_t* model_data; /* байты .onnx, загруженные в память (для file-версии) */ |
|
|
|
|
size_t model_len; |
|
|
|
|
}; |
|
|
|
|
@ -124,7 +128,8 @@ static silero_vad_t* silero_vad_create_from_bytes(const uint8_t* data, size_t le
|
|
|
|
|
|
|
|
|
|
ort->ReleaseSessionOptions(opts); |
|
|
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_VAD, "silero_vad_create(%s): ok bytes=%zu", label, len); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_VAD, "silero_vad_create(%s): ok bytes=%zu window=%d context=%d input=%d", label, len, |
|
|
|
|
SILERO_VAD_WINDOW_SAMPLES, SILERO_VAD_CONTEXT_SAMPLES, SILERO_VAD_INPUT_SAMPLES); |
|
|
|
|
return vad; |
|
|
|
|
|
|
|
|
|
fail: |
|
|
|
|
@ -168,7 +173,8 @@ void silero_vad_destroy(silero_vad_t* vad) {
|
|
|
|
|
void silero_vad_reset(silero_vad_t* vad) { |
|
|
|
|
if (!vad) return; |
|
|
|
|
memset(vad->state, 0, sizeof(vad->state)); |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_VAD, "silero_vad_reset"); |
|
|
|
|
memset(vad->context, 0, sizeof(vad->context)); |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_VAD, "silero_vad_reset: recurrent state and audio context cleared"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int silero_vad_process(silero_vad_t* vad, const float* samples, float* prob) { |
|
|
|
|
@ -183,12 +189,13 @@ int silero_vad_process(silero_vad_t* vad, const float* samples, float* prob) {
|
|
|
|
|
const char* output_names[2]; |
|
|
|
|
const OrtValue* inputs[3]; |
|
|
|
|
OrtValue* outputs[2]; |
|
|
|
|
int64_t shape_input[2] = {1, SILERO_VAD_WINDOW_SAMPLES}; |
|
|
|
|
int64_t shape_input[2] = {1, SILERO_VAD_INPUT_SAMPLES}; |
|
|
|
|
int64_t shape_state[3] = {2, 1, 128}; |
|
|
|
|
int64_t shape_prob[2] = {1, 1}; |
|
|
|
|
int64_t sr_value = SILERO_VAD_SAMPLE_RATE; |
|
|
|
|
float prob_local = 0.0f; |
|
|
|
|
float next_state[SILERO_VAD_STATE_COUNT]; |
|
|
|
|
float input[SILERO_VAD_INPUT_SAMPLES]; |
|
|
|
|
int rc = -1; |
|
|
|
|
|
|
|
|
|
if (!vad || !samples || !prob) { |
|
|
|
|
@ -196,9 +203,11 @@ int silero_vad_process(silero_vad_t* vad, const float* samples, float* prob) {
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
ort = vad->ort; |
|
|
|
|
memcpy(input, vad->context, sizeof(vad->context)); |
|
|
|
|
memcpy(input + SILERO_VAD_CONTEXT_SAMPLES, samples, SILERO_VAD_WINDOW_SAMPLES * sizeof(float)); |
|
|
|
|
|
|
|
|
|
status = ort->CreateTensorWithDataAsOrtValue(vad->mem_info, (void*)samples, |
|
|
|
|
SILERO_VAD_WINDOW_SAMPLES * sizeof(float), shape_input, 2, |
|
|
|
|
status = ort->CreateTensorWithDataAsOrtValue(vad->mem_info, input, |
|
|
|
|
sizeof(input), shape_input, 2, |
|
|
|
|
ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, &in_input); |
|
|
|
|
if (status) { vad_report_ort_error(ort, status, "input tensor"); return -1; } |
|
|
|
|
|
|
|
|
|
@ -241,6 +250,7 @@ int silero_vad_process(silero_vad_t* vad, const float* samples, float* prob) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
memcpy(vad->state, next_state, sizeof(next_state)); |
|
|
|
|
memcpy(vad->context, input + SILERO_VAD_INPUT_SAMPLES - SILERO_VAD_CONTEXT_SAMPLES, sizeof(vad->context)); |
|
|
|
|
*prob = prob_local; |
|
|
|
|
rc = 0; |
|
|
|
|
|
|
|
|
|
|