2020-08-29 22:40:49 +02:00
/** DFT hook.
*
* @ author Manuel Pitz < manuel . pitz @ eonerc . rwth - aachen . de >
* @ copyright 2014 - 2020 , Institute for Automation of Complex Power Systems , EONERC
* @ license GNU General Public License ( version 3 )
*
* VILLASnode
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/** @addtogroup hooks Hook functions
* @ {
*/
# include <cstring>
2021-02-16 12:49:15 +01:00
# include <cinttypes>
2021-02-16 14:13:49 +01:00
# include <complex>
# include <vector>
2021-02-16 12:49:15 +01:00
2021-02-10 14:54:38 +01:00
# include <villas/dumper.hpp>
2020-08-29 22:40:49 +02:00
# include <villas/hook.hpp>
# include <villas/path.h>
# include <villas/sample.h>
# include <villas/io.h>
# include <villas/plugin.h>
namespace villas {
namespace node {
class DftHook : public Hook {
protected :
2021-02-16 12:53:27 +01:00
enum PaddingType {
2020-09-04 17:24:14 +02:00
ZERO ,
SIG_REPEAT
} ;
2021-02-16 12:53:27 +01:00
enum WindowType {
2020-09-04 17:24:14 +02:00
NONE ,
FLATTOP ,
HANN ,
HAMMING
} ;
2021-02-16 14:13:49 +01:00
std : : shared_ptr < Dumper > origSigSync ;
std : : shared_ptr < Dumper > windowdSigSync ;
std : : shared_ptr < Dumper > phasorPhase ;
std : : shared_ptr < Dumper > phasorAmplitude ;
std : : shared_ptr < Dumper > phasorFreq ;
2020-10-10 20:45:51 +02:00
2021-02-16 13:25:37 +01:00
enum WindowType windowType ;
enum PaddingType paddingType ;
2020-09-04 17:24:14 +02:00
2020-08-29 22:40:49 +02:00
struct format_type * format ;
2021-02-16 14:13:49 +01:00
std : : vector < std : : vector < double > > smpMemory ;
std : : vector < std : : vector < std : : complex < double > > > dftMatrix ;
std : : vector < std : : complex < double > > dftResults ;
std : : vector < double > filterWindowCoefficents ;
std : : vector < double > absDftResults ;
std : : vector < double > absDftFreqs ;
2020-09-04 17:24:14 +02:00
2020-10-12 19:27:32 +02:00
uint64_t dftCalcCnt ;
2021-02-16 13:14:26 +01:00
unsigned sampleRate ;
2021-02-16 11:43:53 +01:00
double startFreqency ;
double endFreqency ;
double frequencyResolution ;
2021-02-16 13:14:26 +01:00
unsigned dftRate ;
unsigned windowSize ;
unsigned windowMultiplier ; /**< Multiplyer for the window to achieve frequency resolution */
unsigned freqCount ; /**< Number of requency bins that are calculated */
2021-02-16 11:43:53 +01:00
bool syncDft ;
uint64_t smpMemPos ;
uint64_t lastSequence ;
2021-02-10 13:06:19 +01:00
2020-08-29 22:40:49 +02:00
std : : complex < double > omega ;
2020-09-03 12:05:45 +02:00
2021-02-16 11:43:53 +01:00
double windowCorretionFactor ;
2021-02-16 13:25:37 +01:00
struct timespec lastDftCal ;
2020-08-31 18:09:25 +02:00
2021-02-16 14:13:49 +01:00
std : : vector < int > signalIndex ; /**< A list of signalIndex to do dft on */
2021-02-10 13:06:19 +01:00
2020-08-29 22:40:49 +02:00
public :
2020-10-07 15:52:43 +02:00
DftHook ( struct vpath * p , struct vnode * n , int fl , int prio , bool en = true ) :
2020-08-29 22:40:49 +02:00
Hook ( p , n , fl , prio , en ) ,
2021-02-16 12:53:27 +01:00
windowType ( WindowType : : NONE ) ,
paddingType ( PaddingType : : ZERO ) ,
2021-02-16 14:13:49 +01:00
smpMemory ( ) ,
dftMatrix ( ) ,
dftResults ( ) ,
filterWindowCoefficents ( ) ,
absDftResults ( ) ,
absDftFreqs ( ) ,
2020-10-12 19:27:32 +02:00
dftCalcCnt ( 0 ) ,
2021-02-16 11:43:53 +01:00
sampleRate ( 0 ) ,
startFreqency ( 0 ) ,
endFreqency ( 0 ) ,
frequencyResolution ( 0 ) ,
dftRate ( 0 ) ,
windowSize ( 0 ) ,
windowMultiplier ( 0 ) ,
freqCount ( 0 ) ,
syncDft ( 0 ) ,
smpMemPos ( 0 ) ,
lastSequence ( 0 ) ,
windowCorretionFactor ( 0 ) ,
2021-02-16 13:16:38 +01:00
lastDftCal ( { 0 , 0 } ) ,
2021-02-16 14:13:49 +01:00
signalIndex ( )
2020-08-29 22:40:49 +02:00
{
format = format_type_lookup ( " villas.human " ) ;
2020-10-10 20:45:51 +02:00
2021-02-16 14:13:49 +01:00
bool debug = false ;
if ( debug ) {
origSigSync = std : : make_shared < Dumper > ( " /tmp/plot/origSigSync " ) ;
windowdSigSync = std : : make_shared < Dumper > ( " /tmp/plot/windowdSigSync " ) ;
phasorPhase = std : : make_shared < Dumper > ( " /tmp/plot/phasorPhase " ) ;
phasorAmplitude = std : : make_shared < Dumper > ( " /tmp/plot/phasorAmplitude " ) ;
phasorFreq = std : : make_shared < Dumper > ( " /tmp/plot/phasorFreq " ) ;
}
2020-10-21 21:04:28 +02:00
}
2020-08-29 22:40:49 +02:00
2021-02-10 13:06:19 +01:00
virtual void prepare ( )
{
2020-10-21 21:04:28 +02:00
signal_list_clear ( & signals ) ;
2021-02-16 13:16:38 +01:00
/* Initialize sample memory */
2021-02-16 14:41:55 +01:00
smpMemory . clear ( ) ;
2021-02-16 14:13:49 +01:00
for ( unsigned i = 0 ; i < signalIndex . size ( ) ; i + + ) {
2020-10-21 21:04:28 +02:00
struct signal * freqSig ;
struct signal * amplSig ;
struct signal * phaseSig ;
struct signal * rocofSig ;
2020-09-04 17:24:14 +02:00
2020-10-21 21:04:28 +02:00
/* Add signals */
freqSig = signal_create ( " amplitude " , nullptr , SignalType : : FLOAT ) ;
amplSig = signal_create ( " phase " , nullptr , SignalType : : FLOAT ) ;
phaseSig = signal_create ( " frequency " , nullptr , SignalType : : FLOAT ) ;
rocofSig = signal_create ( " rocof " , nullptr , SignalType : : FLOAT ) ;
2020-09-04 17:24:14 +02:00
2020-10-21 21:04:28 +02:00
if ( ! freqSig | | ! amplSig | | ! phaseSig | | ! rocofSig )
throw RuntimeError ( " Failed to create new signals " ) ;
2020-09-04 21:06:23 +02:00
2020-10-21 21:04:28 +02:00
vlist_push ( & signals , freqSig ) ;
vlist_push ( & signals , amplSig ) ;
vlist_push ( & signals , phaseSig ) ;
vlist_push ( & signals , rocofSig ) ;
2020-09-04 17:24:14 +02:00
2021-02-16 14:13:49 +01:00
smpMemory . emplace_back ( windowSize , 0.0 ) ;
2020-10-21 21:04:28 +02:00
}
2020-09-04 17:24:14 +02:00
2021-02-16 13:16:38 +01:00
/* Calculate how much zero padding ist needed for a needed resolution */
windowMultiplier = ceil ( ( ( double ) sampleRate / windowSize ) / frequencyResolution ) ;
2020-09-04 17:24:14 +02:00
2021-02-16 11:43:53 +01:00
freqCount = ceil ( ( endFreqency - startFreqency ) / frequencyResolution ) + 1 ;
2020-09-10 14:57:45 +02:00
2021-02-16 13:16:38 +01:00
/* Initialize matrix of dft coeffients */
2021-02-16 14:41:55 +01:00
dftMatrix . clear ( ) ;
2021-02-16 14:13:49 +01:00
for ( unsigned i = 0 ; i < freqCount ; i + + )
dftMatrix . emplace_back ( windowSize * windowMultiplier , 0.0 ) ;
2021-02-10 13:06:19 +01:00
2021-02-16 14:13:49 +01:00
dftResults . resize ( freqCount ) ;
filterWindowCoefficents . resize ( windowSize ) ;
absDftResults . resize ( freqCount ) ;
absDftFreqs . resize ( freqCount ) ;
2021-02-16 10:27:08 +01:00
2021-02-16 14:13:49 +01:00
for ( unsigned i = 0 ; i < absDftFreqs . size ( ) ; i + + )
2021-02-16 11:43:53 +01:00
absDftFreqs [ i ] = startFreqency + i * frequencyResolution ;
2021-02-10 13:06:19 +01:00
2021-02-16 09:36:14 +01:00
generateDftMatrix ( ) ;
2021-02-16 13:16:38 +01:00
calculateWindow ( windowType ) ;
2020-08-29 22:40:49 +02:00
state = State : : PREPARED ;
}
virtual void parse ( json_t * cfg )
{
2021-02-16 11:43:53 +01:00
const char * paddingTypeC = nullptr , * windowTypeC = nullptr ;
2020-09-04 17:24:14 +02:00
int ret ;
json_error_t err ;
2020-08-29 22:40:49 +02:00
2021-02-16 11:43:53 +01:00
json_t * jsonChannelList = nullptr ;
2020-10-21 21:04:28 +02:00
2020-08-29 22:40:49 +02:00
assert ( state ! = State : : STARTED ) ;
Hook : : parse ( cfg ) ;
2020-10-21 21:04:28 +02:00
ret = json_unpack_ex ( cfg , & err , 0 , " { s?: i, s?: F, s?: F, s?: F, s?: i , s?: i, s?: s, s?: s, s?: b, s?: o} " ,
2021-02-16 12:47:56 +01:00
" sample_rate " , & sampleRate ,
" start_freqency " , & startFreqency ,
" end_freqency " , & endFreqency ,
" frequency_resolution " , & frequencyResolution ,
" dft_rate " , & dftRate ,
" window_size " , & windowSize ,
" window_type " , & windowTypeC ,
" padding_type " , & paddingTypeC ,
2021-02-16 11:43:53 +01:00
" sync " , & syncDft ,
2021-02-16 12:47:56 +01:00
" signal_index " , & jsonChannelList
2020-09-04 17:24:14 +02:00
) ;
2021-02-16 11:53:42 +01:00
if ( ret )
throw ConfigError ( cfg , err , " node-config-hook-dft " ) ;
2020-09-04 17:24:14 +02:00
2021-02-16 11:43:53 +01:00
if ( jsonChannelList ! = nullptr ) {
2021-02-16 14:13:49 +01:00
signalIndex . clear ( ) ;
2021-02-16 11:43:53 +01:00
if ( jsonChannelList - > type = = JSON_ARRAY ) {
2020-10-21 21:04:28 +02:00
size_t i ;
2021-02-16 11:43:53 +01:00
json_t * jsonValue ;
json_array_foreach ( jsonChannelList , i , jsonValue ) {
if ( ! json_is_number ( jsonValue ) )
throw ConfigError ( jsonValue , " node-config-hook-dft-channel " , " Values must be given as array of integer values! " ) ;
2021-02-16 14:13:49 +01:00
auto idx = json_number_value ( jsonValue ) ;
signalIndex . push_back ( idx ) ;
2020-10-21 21:04:28 +02:00
}
2021-02-10 13:06:19 +01:00
}
2021-02-16 11:43:53 +01:00
else if ( jsonChannelList - > type = = JSON_INTEGER ) {
if ( ! json_is_number ( jsonChannelList ) )
throw ConfigError ( jsonChannelList , " node-config-hook-dft-channel " , " Value must be given as integer value! " ) ;
2021-02-16 14:13:49 +01:00
auto idx = json_number_value ( jsonChannelList ) ;
signalIndex . push_back ( idx ) ;
2020-10-21 21:04:28 +02:00
}
else
2021-02-16 14:15:14 +01:00
logger - > warn ( " Could not parse channel list. Please check documentation for syntax " ) ;
2020-10-21 21:04:28 +02:00
}
else
2021-02-16 12:47:56 +01:00
throw ConfigError ( jsonChannelList , " node-config-node-signal " , " No parameter signalIndex given. " ) ;
2020-10-21 21:04:28 +02:00
2021-02-16 11:43:53 +01:00
if ( ! windowTypeC ) {
2021-02-16 14:15:14 +01:00
logger - > info ( " No Window type given, assume no windowing " ) ;
2021-02-16 12:53:27 +01:00
windowType = WindowType : : NONE ;
2021-02-10 13:06:19 +01:00
}
2021-02-16 11:43:53 +01:00
else if ( strcmp ( windowTypeC , " flattop " ) = = 0 )
2021-02-16 12:53:27 +01:00
windowType = WindowType : : FLATTOP ;
2021-02-16 11:43:53 +01:00
else if ( strcmp ( windowTypeC , " hamming " ) = = 0 )
2021-02-16 12:53:27 +01:00
windowType = WindowType : : HAMMING ;
2021-02-16 11:43:53 +01:00
else if ( strcmp ( windowTypeC , " hann " ) = = 0 )
2021-02-16 12:53:27 +01:00
windowType = WindowType : : HANN ;
2020-09-04 17:24:14 +02:00
else {
2021-02-16 14:15:14 +01:00
logger - > info ( " Window type {} not recognized, assume no windowing " , windowTypeC ) ;
2021-02-16 12:53:27 +01:00
windowType = WindowType : : NONE ;
2020-09-04 17:24:14 +02:00
}
2021-02-16 11:43:53 +01:00
if ( ! paddingTypeC ) {
2021-02-16 14:15:14 +01:00
logger - > info ( " No Padding type given, assume no zeropadding " ) ;
2021-02-16 12:53:27 +01:00
paddingType = PaddingType : : ZERO ;
2020-10-21 21:04:28 +02:00
}
2021-02-16 11:43:53 +01:00
else if ( strcmp ( paddingTypeC , " signal_repeat " ) = = 0 )
2021-02-16 12:53:27 +01:00
paddingType = PaddingType : : SIG_REPEAT ;
2020-10-21 21:04:28 +02:00
else {
2021-02-16 14:15:14 +01:00
logger - > info ( " Padding type {} not recognized, assume zero padding " , paddingTypeC ) ;
2021-02-16 12:53:27 +01:00
paddingType = PaddingType : : ZERO ;
2021-02-10 13:06:19 +01:00
}
2020-09-04 17:24:14 +02:00
2021-02-16 11:53:42 +01:00
if ( endFreqency < 0 | | endFreqency > sampleRate )
2021-02-16 13:16:38 +01:00
throw ConfigError ( cfg , err , " node-config-hook-dft " , " End frequency must be smaller than sampleRate {} " , sampleRate ) ;
2021-02-16 11:53:42 +01:00
if ( frequencyResolution > ( ( double ) sampleRate / windowSize ) )
2021-02-16 13:16:38 +01:00
throw ConfigError ( cfg , err , " node-config-hook-dft " , " The maximum frequency resolution with smaple_rate:{} and window_site:{} is {} " , sampleRate , windowSize , ( ( double ) sampleRate / windowSize ) ) ;
2020-09-04 17:24:14 +02:00
2021-02-16 13:16:38 +01:00
state = State : : PARSED ;
2020-08-29 22:40:49 +02:00
}
2021-02-16 13:16:38 +01:00
virtual Hook : : Reason process ( struct sample * smp )
2020-08-29 22:40:49 +02:00
{
assert ( state = = State : : STARTED ) ;
2021-02-16 13:14:26 +01:00
2021-02-16 14:13:49 +01:00
for ( unsigned i = 0 ; i < signalIndex . size ( ) ; i + + )
2021-02-16 11:43:53 +01:00
smpMemory [ i ] [ smpMemPos % windowSize ] = smp - > data [ signalIndex [ i ] ] . f ;
2021-02-16 10:19:04 +01:00
2021-02-16 11:43:53 +01:00
smpMemPos + + ;
2020-09-01 21:18:00 +02:00
2020-09-10 14:57:45 +02:00
bool runDft = false ;
2021-02-16 11:43:53 +01:00
if ( syncDft ) {
if ( lastDftCal . tv_sec ! = smp - > ts . origin . tv_sec )
2020-09-10 14:57:45 +02:00
runDft = true ;
2020-09-04 21:06:23 +02:00
}
2021-02-16 13:16:38 +01:00
2021-02-16 11:43:53 +01:00
lastDftCal = smp - > ts . origin ;
2021-02-10 13:06:19 +01:00
2020-10-21 21:04:28 +02:00
if ( runDft ) {
2021-02-16 14:13:49 +01:00
for ( unsigned i = 0 ; i < signalIndex . size ( ) ; i + + ) {
2021-02-16 13:16:38 +01:00
calculateDft ( PaddingType : : ZERO , smpMemory [ i ] , smpMemPos ) ;
2020-10-21 21:04:28 +02:00
double maxF = 0 ;
double maxA = 0 ;
int maxPos = 0 ;
2021-02-16 13:14:26 +01:00
for ( unsigned i = 0 ; i < freqCount ; i + + ) {
2021-02-16 12:53:27 +01:00
absDftResults [ i ] = abs ( dftResults [ i ] ) * 2 / ( windowSize * windowCorretionFactor * ( ( paddingType = = PaddingType : : ZERO ) ? 1 : windowMultiplier ) ) ;
2020-10-21 21:04:28 +02:00
if ( maxA < absDftResults [ i ] ) {
maxF = absDftFreqs [ i ] ;
maxA = absDftResults [ i ] ;
maxPos = i ;
}
2020-09-04 21:06:23 +02:00
}
2020-10-12 19:27:32 +02:00
2020-10-21 21:04:28 +02:00
if ( dftCalcCnt > 1 ) {
2021-02-16 14:13:49 +01:00
if ( phasorFreq )
phasorFreq - > writeData ( 1 , & maxF ) ;
2020-10-21 21:04:28 +02:00
2021-02-16 13:16:38 +01:00
smp - > data [ i * 4 ] . f = maxF ; /* Frequency */
smp - > data [ i * 4 + 1 ] . f = ( maxA / pow ( 2 , 0.5 ) ) ; /* Amplitude */
smp - > data [ i * 4 + 2 ] . f = atan2 ( dftResults [ maxPos ] . imag ( ) , dftResults [ maxPos ] . real ( ) ) ; /* Phase */
smp - > data [ i * 4 + 3 ] . f = 0 ; /* RoCof */
2020-10-21 21:04:28 +02:00
2021-02-16 14:13:49 +01:00
if ( phasorPhase )
phasorPhase - > writeData ( 1 , & ( smp - > data [ i * 4 + 2 ] . f ) ) ;
2020-10-21 21:04:28 +02:00
}
2021-02-10 13:06:19 +01:00
}
2020-10-12 19:27:32 +02:00
dftCalcCnt + + ;
2021-02-16 14:13:49 +01:00
smp - > length = signalIndex . size ( ) * 4 ;
2020-10-12 19:27:32 +02:00
}
2021-02-10 13:06:19 +01:00
2021-02-16 11:43:53 +01:00
if ( ( smp - > sequence - lastSequence ) > 1 )
2021-02-16 14:15:14 +01:00
logger - > warn ( " Calculation is not Realtime. {} sampled missed " , smp - > sequence - lastSequence ) ;
2020-09-04 21:06:23 +02:00
2021-02-16 11:43:53 +01:00
lastSequence = smp - > sequence ;
2020-09-04 17:59:29 +02:00
2020-10-21 21:04:28 +02:00
if ( runDft )
return Reason : : OK ;
2020-10-12 19:27:32 +02:00
2020-10-21 21:04:28 +02:00
return Reason : : SKIP_SAMPLE ;
2020-08-29 22:40:49 +02:00
}
2021-02-16 13:16:38 +01:00
void generateDftMatrix ( )
{
2020-08-29 22:40:49 +02:00
using namespace std : : complex_literals ;
2021-02-16 13:16:38 +01:00
omega = exp ( ( - 2 i * M_PI ) / ( double ) ( windowSize * windowMultiplier ) ) ;
2021-02-16 13:14:26 +01:00
unsigned startBin = floor ( startFreqency / frequencyResolution ) ;
2021-02-10 13:06:19 +01:00
2021-02-16 13:14:26 +01:00
for ( unsigned i = 0 ; i < freqCount ; i + + ) {
for ( unsigned j = 0 ; j < windowSize * windowMultiplier ; j + + )
2020-09-04 17:24:14 +02:00
dftMatrix [ i ] [ j ] = pow ( omega , ( i + startBin ) * j ) ;
2020-08-29 22:40:49 +02:00
}
}
2021-02-16 14:13:49 +01:00
void calculateDft ( enum PaddingType padding , std : : vector < double > & ringBuffer , unsigned ringBufferPos )
2021-02-16 13:16:38 +01:00
{
/* RingBuffer size needs to be equal to windowSize
* prepare sample window The following parts can be combined */
2021-02-16 11:43:53 +01:00
double tmpSmpWindow [ windowSize ] ;
2021-02-10 13:06:19 +01:00
2021-02-16 13:14:26 +01:00
for ( unsigned i = 0 ; i < windowSize ; i + + )
2021-02-16 11:43:53 +01:00
tmpSmpWindow [ i ] = ringBuffer [ ( i + ringBufferPos ) % windowSize ] ;
2020-10-12 19:27:32 +02:00
2021-02-16 14:13:49 +01:00
if ( origSigSync )
origSigSync - > writeData ( windowSize , tmpSmpWindow ) ;
2020-10-12 19:27:32 +02:00
2021-02-16 14:13:49 +01:00
if ( dftCalcCnt > 1 & & phasorAmplitude )
2021-02-16 13:16:38 +01:00
phasorAmplitude - > writeData ( 1 , & tmpSmpWindow [ windowSize - 1 ] ) ;
2020-10-12 19:27:32 +02:00
2021-02-16 13:14:26 +01:00
for ( unsigned i = 0 ; i < windowSize ; i + + )
2021-02-16 11:43:53 +01:00
tmpSmpWindow [ i ] * = filterWindowCoefficents [ i ] ;
2021-02-10 13:06:19 +01:00
2021-02-16 14:13:49 +01:00
if ( windowdSigSync )
windowdSigSync - > writeData ( windowSize , tmpSmpWindow ) ;
2020-09-01 21:18:00 +02:00
2021-02-16 13:14:26 +01:00
for ( unsigned i = 0 ; i < freqCount ; i + + ) {
2020-08-29 22:40:49 +02:00
dftResults [ i ] = 0 ;
2021-02-16 13:14:26 +01:00
for ( unsigned j = 0 ; j < windowSize * windowMultiplier ; j + + ) {
2021-02-16 12:53:27 +01:00
if ( padding = = PaddingType : : ZERO ) {
2021-02-16 11:43:53 +01:00
if ( j < ( windowSize ) )
dftResults [ i ] + = tmpSmpWindow [ j ] * dftMatrix [ i ] [ j ] ;
2021-02-10 13:06:19 +01:00
else
dftResults [ i ] + = 0 ;
2020-10-21 21:04:28 +02:00
}
2021-02-16 13:16:38 +01:00
else if ( padding = = PaddingType : : SIG_REPEAT ) /* Repeat samples */
2021-02-16 11:43:53 +01:00
dftResults [ i ] + = tmpSmpWindow [ j % windowSize ] * dftMatrix [ i ] [ j ] ;
2020-08-29 22:40:49 +02:00
}
}
}
2020-08-31 11:48:35 +02:00
2021-02-16 13:16:38 +01:00
void calculateWindow ( enum WindowType windowTypeIn )
{
switch ( windowTypeIn ) {
case WindowType : : FLATTOP :
for ( unsigned i = 0 ; i < windowSize ; i + + ) {
filterWindowCoefficents [ i ] = 0.21557895
- 0.41663158 * cos ( 2 * M_PI * i / ( windowSize ) )
+ 0.277263158 * cos ( 4 * M_PI * i / ( windowSize ) )
- 0.083578947 * cos ( 6 * M_PI * i / ( windowSize ) )
+ 0.006947368 * cos ( 8 * M_PI * i / ( windowSize ) ) ;
windowCorretionFactor + = filterWindowCoefficents [ i ] ;
}
break ;
2020-09-04 17:24:14 +02:00
2021-02-16 13:16:38 +01:00
case WindowType : : HAMMING :
case WindowType : : HANN : {
double a0 = 0.5 ; /* This is the hann window */
if ( windowTypeIn = = WindowType : : HAMMING )
a0 = 25. / 46 ;
for ( unsigned i = 0 ; i < windowSize ; i + + ) {
filterWindowCoefficents [ i ] = a0 - ( 1 - a0 ) * cos ( 2 * M_PI * i / ( windowSize ) ) ;
windowCorretionFactor + = filterWindowCoefficents [ i ] ;
}
break ;
2020-09-03 12:05:45 +02:00
}
2021-02-16 13:16:38 +01:00
default :
for ( unsigned i = 0 ; i < windowSize ; i + + ) {
filterWindowCoefficents [ i ] = 1 ;
windowCorretionFactor + = filterWindowCoefficents [ i ] ;
}
break ;
2020-08-31 11:48:35 +02:00
}
2021-02-16 13:16:38 +01:00
2021-02-16 11:43:53 +01:00
windowCorretionFactor / = windowSize ;
2020-08-31 11:48:35 +02:00
}
2020-08-29 22:40:49 +02:00
} ;
/* Register hook */
static char n [ ] = " dft " ;
static char d [ ] = " This hook calculates the dft on a window " ;
static HookPlugin < DftHook , n , d , ( int ) Hook : : Flags : : NODE_READ | ( int ) Hook : : Flags : : NODE_WRITE | ( int ) Hook : : Flags : : PATH > p ;
} /* namespace node */
} /* namespace villas */
/** @} */