|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
#include <stdio.h>
|
|
|
#include <stdlib.h>
|
|
|
#include <string.h>
|
|
|
|
|
|
#include "stft.h"
|
|
|
#include "stft_st.h"
|
|
|
#include "fftw.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 (memPtrExt == NULL) {
|
|
|
return (totalMemSize);
|
|
|
}
|
|
|
|
|
|
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
|
if (AUP_Analyzer_publishStaticCfg(stHdl) < 0) {
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
|
|
|
totalMemSize = AUP_Analyzer_dynamMemPrepare(stHdl, NULL, 0);
|
|
|
if (totalMemSize < 0) {
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
|