Not savy implementation of exponential time weighting of spectrograms

This commit is contained in:
Anne de Jong 2018-04-01 10:58:55 +02:00 committed by Anne de Jong
parent b3d60a2d69
commit c8332f7f74
3 changed files with 136 additions and 28 deletions

View File

@ -31,14 +31,27 @@ typedef struct AvPowerSpectra_s {
dFifo* fifo; /* Sample fifo storage */ dFifo* fifo; /* Sample fifo storage */
cmat ps_storage; /**< Here we store the averaged cmat* ps_storage; /**< Here we store the averaged
* results for each Cross-power * results for each Cross-power
* spectra computed so far. */ * spectra computed so far. */
cmat ps_result;
cmat ps_single; /**< This is the work area for a cmat ps_single; /**< This is the work area for a
* PowerSpectra computation on a * PowerSpectra computation on a
* single block */ * single block */
vd weighting; /**< This array stores the time weighting
* coefficients for a running
* spectrogram. The vector length is
* zero for a full averaged (not
* running spectrogram). */
us oldest_block; /**< Index of oldest block in
* Spectrogram mode */
PowerSpectra* ps; /**< Pointer to underlying PowerSpectra* ps; /**< Pointer to underlying
* PowerSpectra calculator. */ * PowerSpectra calculator. */
@ -50,8 +63,18 @@ void AvPowerSpectra_free(AvPowerSpectra* aps) {
PowerSpectra_free(aps->ps); PowerSpectra_free(aps->ps);
dFifo_free(aps->fifo); dFifo_free(aps->fifo);
dmat_free(&aps->buffer); dmat_free(&aps->buffer);
cmat_free(&aps->ps_storage);
us nweight = aps->weighting.size;
if(nweight > 0) {
for(us blockno = 0; blockno < nweight; blockno++) {
cmat_free(&aps->ps_storage[blockno]);
}
a_free(aps->ps_storage);
vd_free(&aps->weighting);
}
cmat_free(&aps->ps_single); cmat_free(&aps->ps_single);
cmat_free(&aps->ps_result);
a_free(aps); a_free(aps);
feTRACE(15); feTRACE(15);
@ -60,7 +83,8 @@ void AvPowerSpectra_free(AvPowerSpectra* aps) {
AvPowerSpectra* AvPowerSpectra_alloc(const us nfft, AvPowerSpectra* AvPowerSpectra_alloc(const us nfft,
const us nchannels, const us nchannels,
const d overlap_percentage, const d overlap_percentage,
const WindowType wt) { const WindowType wt,
const vd* weighting) {
fsTRACE(15); fsTRACE(15);
@ -99,15 +123,34 @@ AvPowerSpectra* AvPowerSpectra_alloc(const us nfft,
aps->ps = ps; aps->ps = ps;
aps->naverages = 0; aps->naverages = 0;
aps->overlap = overlap; aps->overlap = overlap;
aps->buffer = dmat_alloc(nfft,nchannels); aps->buffer = dmat_alloc(nfft,nchannels);
aps->oldest_block = 0;
if(weighting) {
us nweight = weighting->size;
iVARTRACE(15,nweight);
/* Allocate vectors and matrices */
aps->ps_storage = a_malloc(nweight*sizeof(cmat));
for(us blockno = 0; blockno < nweight; blockno++) {
aps->ps_storage[blockno] = cmat_alloc(nfft/2+1,nchannels*nchannels);
cmat_set(&aps->ps_storage[blockno],0);
}
/* Allocate vectors and matrices */ /* Allocate space and copy weighting coefficients */
aps->ps_storage = cmat_alloc(nfft/2+1,nchannels*nchannels); aps->weighting = vd_alloc(weighting->size);
vd_copy(&aps->weighting,weighting);
}
else {
TRACE(15,"no weighting");
aps->weighting.size = 0;
}
aps->ps_result = cmat_alloc(nfft/2+1,nchannels*nchannels);
aps->ps_single = cmat_alloc(nfft/2+1,nchannels*nchannels); aps->ps_single = cmat_alloc(nfft/2+1,nchannels*nchannels);
cmat_set(&aps->ps_result,0);
aps->fifo = dFifo_create(nchannels,FIFO_SIZE_MULT*nfft); aps->fifo = dFifo_create(nchannels,FIFO_SIZE_MULT*nfft);
cmat_set(&aps->ps_storage,0);
feTRACE(15); feTRACE(15);
return aps; return aps;
} }
@ -135,23 +178,69 @@ static void AvPowerSpectra_addBlock(AvPowerSpectra* aps,
iVARTRACE(15,nfft); iVARTRACE(15,nfft);
cmat* ps_single = &aps->ps_single; cmat* ps_single = &aps->ps_single;
cmat* ps_storage = &aps->ps_storage; cmat* ps_storage = aps->ps_storage;
cmat* ps_result = &aps->ps_result;
c naverages = (++aps->naverages);
/* Scale previous result */
cmat_scale(ps_storage,
(naverages-1)/naverages);
PowerSpectra_compute(aps->ps, PowerSpectra_compute(aps->ps,
block, block,
ps_single); ps_single);
vd weighting = aps->weighting;
us nweight = weighting.size;
if(nweight == 0) {
/* Overall mode */
c naverages = (++aps->naverages);
/* Scale previous result */
cmat_scale(ps_result,
(naverages-1)/naverages);
/* Add new result, scaled properly */
cmat_add_cmat(ps_result,
ps_single,1/naverages);
}
else {
cmat_set(ps_result,0);
us* oldest_block = &aps->oldest_block;
/* uVARTRACE(20,*oldest_block); */
cmat_copy(&ps_storage[*oldest_block],ps_single);
uVARTRACE(16,*oldest_block);
if(aps->naverages < nweight) {
++(aps->naverages);
}
/* Update pointer to oldest block */
(*oldest_block)++;
*oldest_block %= nweight;
us block_index_weight = *oldest_block;
for(us block = 0; block < aps->naverages; block++) {
/* Add new result, scaled properly */
c weight_fac = *getvdval(&weighting,
aps->naverages-1-block);
/* cVARTRACE(20,weight_fac); */
cmat_add_cmat(ps_result,
&ps_storage[block_index_weight],
weight_fac);
block_index_weight++;
block_index_weight %= nweight;
/* Add new result, scaled properly */ }
cmat_add_cmat(ps_storage,
ps_single,1/naverages);
}
feTRACE(15); feTRACE(15);
} }
@ -193,7 +282,7 @@ cmat* AvPowerSpectra_addTimeData(AvPowerSpectra* aps,
} }
feTRACE(15); feTRACE(15);
return &aps->ps_storage; return &aps->ps_result;
} }

View File

@ -12,6 +12,12 @@
#include "lasp_math.h" #include "lasp_math.h"
#include "lasp_window.h" #include "lasp_window.h"
typedef enum {
Linear=0,
Exponential=1
} TimeWeighting;
typedef struct AvPowerSpectra_s AvPowerSpectra; typedef struct AvPowerSpectra_s AvPowerSpectra;
/** /**
@ -35,8 +41,9 @@ typedef struct AvPowerSpectra_s AvPowerSpectra;
AvPowerSpectra* AvPowerSpectra_alloc(const us nfft, AvPowerSpectra* AvPowerSpectra_alloc(const us nfft,
const us nchannels, const us nchannels,
const d overlap_percentage, const d overlap_percentage,
const WindowType wt); const WindowType wt,
const vd* spectrogram_weighting);
/** /**
* Computes the real overlap percentage, from the integer overlap * Computes the real overlap percentage, from the integer overlap

View File

@ -183,7 +183,8 @@ cdef extern from "lasp_aps.h":
c_AvPowerSpectra* AvPowerSpectra_alloc(const us nfft, c_AvPowerSpectra* AvPowerSpectra_alloc(const us nfft,
const us nchannels, const us nchannels,
d overlap_percentage, d overlap_percentage,
const WindowType wt) const WindowType wt,
const vd* weighting)
cmat* AvPowerSpectra_addTimeData(const c_AvPowerSpectra* ps, cmat* AvPowerSpectra_addTimeData(const c_AvPowerSpectra* ps,
const dmat * timedata) const dmat * timedata)
@ -200,11 +201,22 @@ cdef class AvPowerSpectra:
def __cinit__(self,us nfft, def __cinit__(self,us nfft,
us nchannels, us nchannels,
d overlap_percentage, d overlap_percentage,
us window=rectangular): us window=Window.rectangular,
d[:] weighting = np.array([])):
cdef vd weighting_vd
cdef vd* weighting_ptr = NULL
if(weighting.size != 0):
weighting_vd = vd_foreign(weighting.size,
&weighting[0])
weighting_ptr = &weighting_vd
self.aps = AvPowerSpectra_alloc(nfft, self.aps = AvPowerSpectra_alloc(nfft,
nchannels, nchannels,
overlap_percentage, overlap_percentage,
<WindowType> window) <WindowType> window,
weighting_ptr)
self.nchannels = nchannels self.nchannels = nchannels
self.nfft = nfft self.nfft = nfft