ten-vad / src /stft.cc
Ziyi Lin
ONNX open source and license terms update
b50f2a2
raw
history blame
7.58 kB
//
// Copyright © 2025 Agora
// This file is part of TEN Framework, an open source project.
// Licensed under the Apache License, Version 2.0, with certain conditions.
// Refer to the "LICENSE" file in the root directory for more information.
//
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stft.h"
#include "stft_st.h"
#include "fftw.h"
// ==========================================================================================
// internal tools
// ==========================================================================================
static int AUP_Analyzer_checkStatCfg(Analyzer_StaticCfg* pCfg) {
if (pCfg == NULL) {
return -1;
}
if (pCfg->fft_size != 256 && pCfg->fft_size != 512 &&
pCfg->fft_size != 1024 && pCfg->fft_size != 2048 &&
pCfg->fft_size != 4096) {
return -1;
}
if (pCfg->win_len <= 0 || pCfg->win_len < pCfg->hop_size ||
pCfg->win_len > pCfg->fft_size) {
return -1;
}
if (pCfg->hop_size <= 0) {
return -1;
}
return 0;
}
static int AUP_Analyzer_publishStaticCfg(Analyzer_St* stHdl) {
const Analyzer_StaticCfg* pStatCfg;
int idx;
if (stHdl == NULL) {
return -1;
}
pStatCfg = (const Analyzer_StaticCfg*)(&(stHdl->stCfg));
stHdl->nBins = (pStatCfg->fft_size >> 1) + 1;
if (pStatCfg->ana_win_coeff != NULL) {
memcpy(stHdl->windowCoffCopy, pStatCfg->ana_win_coeff,
sizeof(float) * pStatCfg->win_len);
} else {
for (idx = 0; idx < AUP_STFT_MAX_FFTSZ; idx++) {
stHdl->windowCoffCopy[idx] = 1.0f;
}
}
return 0;
}
static int AUP_Analyzer_resetVariables(Analyzer_St* stHdl) {
memset(stHdl->dynamMemPtr, 0, stHdl->dynamMemSize);
return 0;
}
static int AUP_Analyzer_dynamMemPrepare(Analyzer_St* stHdl, void* memPtrExt,
size_t memSize) {
int inputQMemSz = 0;
int fftInputBufMemSz = 0;
int totalMemSize = 0;
char* memPtr = NULL;
inputQMemSz = AUP_STFT_ALIGN8(sizeof(float) * (stHdl->stCfg.win_len + 4));
totalMemSize += inputQMemSz;
fftInputBufMemSz =
AUP_STFT_ALIGN8(sizeof(float) * (stHdl->stCfg.fft_size + 4));
totalMemSize += fftInputBufMemSz;
// if no external memory provided, we are only profiling the memory
// requirement
if (memPtrExt == NULL) {
return (totalMemSize);
}
// if required memory is more than provided, error
if ((size_t)totalMemSize > memSize) {
return -1;
}
memPtr = (char*)memPtrExt;
stHdl->inputQ = (float*)memPtr;
memPtr += inputQMemSz;
stHdl->fftInputBuf = (float*)memPtr;
memPtr += fftInputBufMemSz;
if (((int)(memPtr - (char*)memPtrExt)) > totalMemSize) {
return -1;
}
return (totalMemSize);
}
// ==========================================================================================
// public APIs
// ==========================================================================================
int AUP_Analyzer_create(void** stPtr) {
Analyzer_St* tmpPtr;
if (stPtr == NULL) {
return -1;
}
*stPtr = (void*)malloc(sizeof(Analyzer_St));
if (*stPtr == NULL) {
return -1;
}
memset(*stPtr, 0, sizeof(Analyzer_St));
tmpPtr = (Analyzer_St*)(*stPtr);
tmpPtr->dynamMemPtr = NULL;
tmpPtr->dynamMemSize = 0;
tmpPtr->stCfg.win_len = 768;
tmpPtr->stCfg.hop_size = 256;
tmpPtr->stCfg.fft_size = 1024;
tmpPtr->stCfg.ana_win_coeff = NULL;
return 0;
}
int AUP_Analyzer_destroy(void** stPtr) {
Analyzer_St* stHdl;
if (stPtr == NULL) {
return 0;
}
stHdl = (Analyzer_St*)(*stPtr);
if (stHdl == NULL) {
return 0;
}
if (stHdl->dynamMemPtr != NULL) {
free(stHdl->dynamMemPtr);
}
stHdl->dynamMemPtr = NULL;
free(stHdl);
(*stPtr) = NULL;
return 0;
}
int AUP_Analyzer_memAllocate(void* stPtr, const Analyzer_StaticCfg* pCfg) {
Analyzer_St* stHdl = NULL;
Analyzer_StaticCfg localStCfg;
int totalMemSize = 0;
if (stPtr == NULL || pCfg == NULL) {
return -1;
}
stHdl = (Analyzer_St*)(stPtr);
memcpy(&localStCfg, pCfg, sizeof(Analyzer_StaticCfg));
if (AUP_Analyzer_checkStatCfg(&localStCfg) < 0) {
return -1;
}
memcpy(&(stHdl->stCfg), &localStCfg, sizeof(Analyzer_StaticCfg));
// 1st. publish internal static configuration registers
if (AUP_Analyzer_publishStaticCfg(stHdl) < 0) {
return -1;
}
// 4th: check memory requirement
totalMemSize = AUP_Analyzer_dynamMemPrepare(stHdl, NULL, 0);
if (totalMemSize < 0) {
return -1;
}
// 5th: allocate dynamic memory
if ((size_t)totalMemSize > stHdl->dynamMemSize) {
if (stHdl->dynamMemPtr != NULL) {
free(stHdl->dynamMemPtr);
stHdl->dynamMemSize = 0;
}
stHdl->dynamMemPtr = malloc(totalMemSize);
if (stHdl->dynamMemPtr == NULL) {
return -1;
}
stHdl->dynamMemSize = totalMemSize;
}
memset(stHdl->dynamMemPtr, 0, stHdl->dynamMemSize);
// 6th: setup the pointers/variable
if (AUP_Analyzer_dynamMemPrepare(stHdl, stHdl->dynamMemPtr,
stHdl->dynamMemSize) < 0) {
return -1;
}
return 0;
}
int AUP_Analyzer_init(void* stPtr) {
Analyzer_St* stHdl;
if (stPtr == NULL) {
return -1;
}
stHdl = (Analyzer_St*)(stPtr);
if (AUP_Analyzer_resetVariables(stHdl) < 0) {
return -1;
}
return 0;
}
int AUP_Analyzer_getStaticCfg(const void* stPtr, Analyzer_StaticCfg* pCfg) {
const Analyzer_St* stHdl;
if (stPtr == NULL || pCfg == NULL) {
return -1;
}
stHdl = (const Analyzer_St*)(stPtr);
memcpy(pCfg, &(stHdl->stCfg), sizeof(Analyzer_StaticCfg));
return 0;
}
int AUP_Analyzer_proc(void* stPtr, const Analyzer_InputData* pIn,
Analyzer_OutputData* pOut) {
Analyzer_St* stHdl = NULL;
int hopSz, fftSz, winLen, nBins;
int idx = 0;
if (stPtr == NULL || pIn == NULL || pIn->input == NULL || pOut == NULL ||
pOut->output == NULL) {
return -1;
}
stHdl = (Analyzer_St*)(stPtr);
if (pIn->iLength != stHdl->stCfg.hop_size ||
pOut->oLength < stHdl->stCfg.fft_size) {
return -1;
}
hopSz = stHdl->stCfg.hop_size;
fftSz = stHdl->stCfg.fft_size;
nBins = (fftSz >> 1) + 1;
winLen = stHdl->stCfg.win_len;
memset(pOut->output, 0, sizeof(float) * pOut->oLength);
memmove(stHdl->inputQ, stHdl->inputQ + hopSz,
sizeof(float) * (winLen - hopSz));
memcpy(stHdl->inputQ + (winLen - hopSz), pIn->input, sizeof(float) * hopSz);
if (stHdl->stCfg.ana_win_coeff != NULL) {
for (idx = 0; idx < winLen; idx++) {
stHdl->fftInputBuf[idx] = stHdl->inputQ[idx] * stHdl->windowCoffCopy[idx];
}
} else {
for (idx = 0; idx < winLen; idx++) {
stHdl->fftInputBuf[idx] = stHdl->inputQ[idx];
}
}
for (; idx < fftSz; idx++) {
stHdl->fftInputBuf[idx] = 0;
}
if (fftSz == 256) {
AUP_FFTW_r2c_256(stHdl->fftInputBuf, pOut->output);
} else if (fftSz == 512) {
AUP_FFTW_r2c_512(stHdl->fftInputBuf, pOut->output);
} else if (fftSz == 1024) {
AUP_FFTW_r2c_1024(stHdl->fftInputBuf, pOut->output);
} else if (fftSz == 2048) {
AUP_FFTW_r2c_2048(stHdl->fftInputBuf, pOut->output);
} else if (fftSz == 4096) {
AUP_FFTW_r2c_4096(stHdl->fftInputBuf, pOut->output);
}
AUP_FFTW_InplaceTransf(1, fftSz, pOut->output);
AUP_FFTW_RescaleFFTOut(fftSz, pOut->output);
return 0;
}