Added dFifo queue for samples. Improved aps.c to handle all sizes of time data to be added

This commit is contained in:
Anne de Jong 2018-02-14 16:56:31 +01:00 committed by J.A. de Jong - ASCEE
parent f23164b743
commit 41eca0506f
8 changed files with 312 additions and 103 deletions

View File

@ -15,6 +15,7 @@ add_library(beamforming_lib
ps.c
mq.c
worker.c
dfifo.c
)

View File

@ -9,13 +9,16 @@
#include "aps.h"
#include "ps.h"
#include "ascee_alg.h"
#include "dfifo.h"
/* Multiplication factor for the maximum size of the fifo queue. This
* factor is multiplied by nfft to obtain the maximum size of the
* fifo. */
#define FIFO_SIZE_MULT (5)
typedef struct AvPowerSpectra_s {
us os; /**< Counter set to the position where
* the next time block should be taken
* from */
us nfft, nchannels;
us oo;
us overlap; /* Number of samples to overlap */
us naverages; /* Counter that counts the number of
* averages taken for the computation
@ -26,6 +29,8 @@ typedef struct AvPowerSpectra_s {
* equal to nfft. */
dFifo* fifo; /* Sample fifo storage */
cmat ps_storage; /**< Here we store the averaged
* results for each Cross-power
* spectra computed so far. */
@ -39,6 +44,19 @@ typedef struct AvPowerSpectra_s {
} AvPowerSpectra;
void AvPowerSpectra_free(AvPowerSpectra* aps) {
fsTRACE(15);
PowerSpectra_free(aps->ps);
dFifo_free(aps->fifo);
dmat_free(&aps->buffer);
cmat_free(&aps->ps_storage);
cmat_free(&aps->ps_single);
a_free(aps);
feTRACE(15);
}
AvPowerSpectra* AvPowerSpectra_alloc(const us nfft,
const us nchannels,
const d overlap_percentage,
@ -47,29 +65,26 @@ AvPowerSpectra* AvPowerSpectra_alloc(const us nfft,
fsTRACE(15);
/* Check nfft */
if(nfft % 2 != 0 || nfft > ASCEE_MAX_NFFT) {
WARN("nfft should be even");
if(nfft==0 || nfft % 2 != 0 || nfft > ASCEE_MAX_NFFT) {
WARN("Invalid nfft");
feTRACE(15);
return NULL;
}
/* Check overlap percentage */
if(overlap_percentage >= 100) {
WARN("Overlap percentage >= 100!");
feTRACE(15);
return NULL;
}
if(overlap_percentage < 0) {
WARN("Overlap percentage should be positive!");
if(overlap_percentage < 0. || overlap_percentage >= 100.) {
WARN("Invalid overlap percentage");
feTRACE(15);
return NULL;
}
/* Compute and check overlap offset */
us oo = (us) (((d) nfft)-overlap_percentage*((d) nfft)/100);
iVARTRACE(15,oo);
if(oo == 0) {oo++;}
us overlap = (us) (overlap_percentage*((d) nfft)/100);
if(overlap == nfft) {
WARN("Overlap percentage results in full overlap, decreasing overlap.");
overlap--;
}
PowerSpectra* ps = PowerSpectra_alloc(nfft,wt);
if(!ps) {
WARN(ALLOCFAILED "ps");
@ -83,14 +98,15 @@ AvPowerSpectra* AvPowerSpectra_alloc(const us nfft,
aps->nfft = nfft;
aps->ps = ps;
aps->naverages = 0;
aps->oo = oo;
aps->os = oo;
aps->overlap = overlap;
aps->buffer = dmat_alloc(nfft,nchannels);
/* Allocate vectors and matrices */
aps->buffer = dmat_alloc(nfft,nchannels);
aps->ps_storage = cmat_alloc(nfft/2+1,nchannels*nchannels);
aps->ps_single = cmat_alloc(nfft/2+1,nchannels*nchannels);
aps->fifo = dFifo_create(nchannels,FIFO_SIZE_MULT*nfft);
cmat_set(&aps->ps_storage,0);
feTRACE(15);
return aps;
@ -142,7 +158,7 @@ static void AvPowerSpectra_addBlock(AvPowerSpectra* aps,
cmat* AvPowerSpectra_addTimeData(AvPowerSpectra* aps,
const dmat* timedata) {
const dmat* timedata) {
fsTRACE(15);
@ -151,92 +167,65 @@ cmat* AvPowerSpectra_addTimeData(AvPowerSpectra* aps,
const us nfft = aps->nfft;
dbgassert(timedata->n_cols == nchannels,"Invalid time data");
dbgassert(timedata->n_rows >= nfft,"Invalid time data. "
"Should at least have nfft rows");
dbgassert(timedata->n_rows > 0,"Invalid time data. "
"Should at least have one row");
const us oo = aps->oo;
us* os = &aps->os;
const us nsamples = timedata->n_rows;
us os_timedata = 0;
/* Split up timedata in blocks of size ~ (FIFO_SIZE_MULT-1)nfft */
const us max_blocksize = (FIFO_SIZE_MULT-1)*nfft;
dmat buffer = aps->buffer;
us pos = 0; /* Current position in timedata buffer */
/* Retrieve the buffer and use it to make the first time block. */
if(*os < oo) {
TRACE(15,"Using saved data from previous run");
dbgassert(false,"not tested")
dmat tmp = dmat_alloc(nfft,nchannels);
dbgassert(0 <= *os,"BUG");
dbgassert(*os <= nfft,"BUG");
/* dFifo handle */
dFifo* fifo = aps->fifo;
/* copy_dmat_rows(&tmp, */
/* &buffer, */
/* *os, /\* Startrow_from *\/ */
/* 0, /\* Startrow to *\/ */
/* nfft - *os /\* nrows *\/ */
/* ); */
do {
us nsamples_part = pos+max_blocksize <= nsamples ?
max_blocksize : nsamples-pos;
/* copy_dmat_rows(&tmp, */
/* timedata, */
/* 0, */
/* nfft - *os, */
/* *os */
/* ); */
AvPowerSpectra_addBlock(aps,&tmp);
os_timedata = oo + *os - nfft;
dbgassert(os_timedata < nfft,"BUG");
dmat_free(&tmp);
}
/* Run until we cannot go any further */
while ((os_timedata + nfft) <= timedata->n_rows) {
dmat tmp = dmat_submat(timedata,
os_timedata, /* Startrow */
0, /* Start column */
nfft, /* Number of rows */
nchannels); /* Number of columns */
/* Process the block of time data */
AvPowerSpectra_addBlock(aps,&tmp);
iVARTRACE(15,os_timedata);
os_timedata += oo;
dmat_free(&tmp);
iVARTRACE(15,os_timedata);
}
/* We copy the last piece of samples from the timedata to the
* buffer */
dmat_copy_rows(&buffer,
timedata,
0, /* startrow_to */
timedata->n_rows-nfft, /* startrow_from */
nfft); /* Number of rows */
/* Obtain sub matrix */
dmat timedata_part = dmat_submat(timedata,
pos, /* Startrow */
0, /* Startcol */
nsamples_part, /* n_rows */
nchannels); /* n_cols */
*os = os_timedata+nfft-timedata->n_rows;
dbgassert(*os <= nfft,"BUG");
if(dFifo_push(fifo,&timedata_part)!=SUCCESS) {
WARN("Fifo push failed.");
}
/* Temporary storage buffer */
dmat* buffer = &aps->buffer;
/* Pop samples from the fifo while there are still at
* least nfft samples available */
while (dFifo_size(fifo) >= nfft) {
int popped = dFifo_pop(fifo,
buffer,
aps->overlap); /* Keep 'overlap'
* number of samples
* in the queue */
dbgassert((us) popped == nfft,"Bug in dFifo");
/* Process the block of time data */
AvPowerSpectra_addBlock(aps,buffer);
}
dmat_free(&timedata_part);
/* Update position */
pos+=nsamples_part;
} while (pos < nsamples);
dbgassert(pos == nsamples,"BUG");
feTRACE(15);
return &aps->ps_storage;
}
void AvPowerSpectra_free(AvPowerSpectra* aps) {
fsTRACE(15);
PowerSpectra_free(aps->ps);
dmat_free(&aps->buffer);
cmat_free(&aps->ps_storage);
cmat_free(&aps->ps_single);
a_free(aps);
feTRACE(15);
}
//////////////////////////////////////////////////////////////////////

View File

@ -116,7 +116,7 @@ static inline c* getcmatval(const cmat* mat,const us row,const us col){
"Buffer overflow detected on" #vx ); \
} \
else { \
WARN("Cannot check overflow on foreign buffer"); \
DBGWARN("Cannot check overflow on foreign buffer"); \
}
#define check_overflow_xmat(xmat) \
@ -127,7 +127,7 @@ static inline c* getcmatval(const cmat* mat,const us row,const us col){
"Buffer overflow detected on" #xmat ); \
} \
else { \
WARN("Cannot check overflow on foreign buffer"); \
DBGWARN("Cannot check overflow on foreign buffer"); \
}
#else
@ -401,7 +401,10 @@ static inline dmat dmat_submat(const dmat* parent,
dbgassert(n_rows+startrow <= parent->n_rows,OUTOFBOUNDSMATR);
dbgassert(n_cols+startcol <= parent->n_cols,OUTOFBOUNDSMATC);
dmat result = { n_rows,n_cols,true,n_rows-startrow,
dmat result = { n_rows,n_cols,
true, // Foreign data = true
parent->n_rows, // This is the stride to get to
// the next column.
getdmatval(parent,startrow,startcol)};
return result;
@ -427,7 +430,11 @@ static inline cmat cmat_submat(cmat* parent,
dbgassert(n_rows+startrow <= parent->n_rows,OUTOFBOUNDSMATR);
dbgassert(n_cols+startcol <= parent->n_cols,OUTOFBOUNDSMATC);
cmat result = { n_rows,n_cols,true,n_rows-startrow,
cmat result = { n_rows,n_cols,
true, // Foreign data = true
parent->n_rows, // This is the stride to get to
// the next column.
getcmatval(parent,startrow,startcol)};
return result;

View File

@ -5,6 +5,7 @@
// Description:
// Operations working on raw arrays of floating point numbers
//////////////////////////////////////////////////////////////////////
#define TRACERPLUS (-5)
#include "ascee_math_raw.h"
#if ASCEE_USE_BLAS
#include <cblas.h>

138
beamforming/c/dfifo.c Normal file
View File

@ -0,0 +1,138 @@
// dfifo.c
//
// Author: J.A. de Jong -ASCEE
//
// Description:
// Implementation of the dFifo queue
//////////////////////////////////////////////////////////////////////
#include "dfifo.h"
#define DFIFO_QUEUE_MAX_BLOCKS (50)
typedef struct dFifo_s {
dmat queue;
us start_row;
us end_row;
} dFifo;
us dFifo_size(dFifo* fifo) {
fsTRACE(15);
dbgassert(fifo,NULLPTRDEREF);
dbgassert(fifo->start_row <= fifo->end_row,"BUG");
feTRACE(15);
return fifo->end_row-fifo->start_row;
}
dFifo* dFifo_create(const us nchannels,
const us max_size) {
fsTRACE(15);
dFifo* fifo = a_malloc(sizeof(dFifo));
fifo->queue = dmat_alloc(max_size,nchannels);
fifo->start_row = 0;
fifo->end_row = 0;
feTRACE(15);
return fifo;
}
void dFifo_free(dFifo* fifo) {
fsTRACE(15);
dmat_free(&fifo->queue);
a_free(fifo);
feTRACE(15);
}
int dFifo_push(dFifo* fifo,const dmat* data) {
fsTRACE(15);
dbgassert(fifo && data, NULLPTRDEREF);
dbgassert(data->n_cols == fifo->queue.n_cols,
"Invalid number of columns in data");
dmat queue = fifo->queue;
const us max_size = queue.n_rows;
const us nchannels = queue.n_cols;
us* start_row = &fifo->start_row;
us* end_row = &fifo->end_row;
const us added_size = data->n_rows;
const us size_before = dFifo_size(fifo);
if(added_size + dFifo_size(fifo) > max_size) {
return FIFO_QUEUE_FULL;
}
if(*end_row + added_size > max_size) {
if(size_before != 0) {
/* Shift the samples to the front of the queue. TODO: this
* might not be the most optimal implementation (but it is the
* most simple). */
TRACE(15,"Shift samples back in buffer");
uVARTRACE(15,size_before);
dmat tmp = dmat_alloc(size_before,nchannels);
TRACE(15,"SFSG");
dmat_copy_rows(&tmp,
&queue,
0,
*start_row,
size_before);
TRACE(15,"SFSG");
dmat_copy_rows(&queue,
&tmp,
0,0,size_before);
*end_row -= *start_row;
*start_row = 0;
dmat_free(&tmp);
}
else {
*start_row = 0;
*end_row = 0;
}
}
/* Now, copy samples */
dmat_copy_rows(&queue, /* to */
data, /* from */
*end_row, /* startrow_to */
0, /* startrow_from */
added_size); /* n_rows */
/* Increase the size */
*end_row += added_size;
feTRACE(15);
return SUCCESS;
}
int dFifo_pop(dFifo* fifo,dmat* data,const us keep) {
fsTRACE(15);
dbgassert(fifo && data,NULLPTRDEREF);
dbgassert(data->n_cols == fifo->queue.n_cols,
"Invalid number of columns in data");
dbgassert(keep < data->n_rows, "Number of samples to keep should"
" be smaller than requested number of samples");
us* start_row = &fifo->start_row;
us* end_row = &fifo->end_row;
us cur_contents = dFifo_size(fifo);
us requested = data->n_rows;
us obtained = requested > cur_contents ? cur_contents : requested;
dbgassert(obtained > keep,"Number of samples to keep should be"
" smaller than requested number of samples");
uVARTRACE(15,requested);
uVARTRACE(15,obtained);
uVARTRACE(15,*start_row);
uVARTRACE(15,*end_row);
dmat_copy_rows(data,
&fifo->queue,
0,
*start_row,
obtained);
*start_row += obtained - keep;
feTRACE(15);
return (int) obtained;
}
//////////////////////////////////////////////////////////////////////

76
beamforming/c/dfifo.h Normal file
View File

@ -0,0 +1,76 @@
// dfifo.h
//
// Author: J.A. de Jong - ASCEE
//
// Description:
// API of a contiguous fifo buffer of samples.
//////////////////////////////////////////////////////////////////////
#pragma once
#ifndef DFIFO_H
#define DFIFO_H
#include "types.h"
#include "ascee_math.h"
typedef struct dFifo_s dFifo;
/**
* Create a fifo buffer
*
* @param nchannels Number of channels to store for
* @param max_size Maximum size of the queue.
*
* @return Pointer to fifo queue.
*/
dFifo* dFifo_create(const us nchannels,
const us max_size);
#define FIFO_QUEUE_FULL (-1)
/**
* Pushes samples into the fifo.
*
* @param fifo dFifo handle
*
* @param data data to push. Number of columns should be equal to
* nchannels.
*
* @return 0 on success, FIFO_QUEUE_FULL when samples do not fit.
*/
int dFifo_push(dFifo* fifo,const dmat* data);
/**
* Pop samples from the queue
*
* @param[in] fifo dFifo handle
* @param[out] data Pointer to dmat where popped data will be
* stored. Should have nchannels number of columns. If n_rows is
* larger than current storage, the queue is emptied.
* @param[in] keep Keeps a number of samples for the next dFifo_pop(). If
* keep=0, then no samples will be left. Keep should be smaller than
* the number of rows in data.
*
* @return Number of samples obtained in data.
*/
int dFifo_pop(dFifo* fifo,dmat* data,const us keep);
/**
* Returns current size of the fifo
*
* @param[in] fifo dFifo handle
*
* @return Current size
*/
us dFifo_size(dFifo* fifo);
/**
* Free a dFifo object
*
* @param[in] fifo dFifo handle.
*/
void dFifo_free(dFifo* fifo);
#endif // DFIFO_H
//////////////////////////////////////////////////////////////////////

View File

@ -144,12 +144,9 @@ void PowerSpectra_compute(const PowerSpectra* ps,
* is documented */
vc res = cmat_column(result,i+j*nchannels);
check_overflow_vx(res);
vc i_vec = cmat_column(&fft_work,i);
vc j_vec = cmat_column(&fft_work,j);
check_overflow_xmat(fft_work);
/* Compute the conjugate of spectra j */
vc_conj(&j_vec_conj,&j_vec);

View File

@ -1,6 +1,6 @@
include "config.pxi"
setTracerLevel(-5)
setTracerLevel(15)
cdef extern from "cblas.h":
int openblas_get_num_threads()
void openblas_set_num_threads(int)