//-------------------------------------------------------------------------------
// Pd Spectral Toolkit
//
// windower.c
//
// Writes window functions into Pd arrays
//
// Created by Cooper Baker on 5/8/12.
// Updated for 64 Bit Support in September 2019.
// Copyright (C) 2019 Cooper Baker. All Rights Reserved.
//-------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// m_pd.h - main header for Pd
//------------------------------------------------------------------------------
// main header for pd
#include "m_pd.h"
// utility header for Pd Spectral Toolkit project
#include "utility.h"
// disable compiler warnings on windows
#ifdef NT
#pragma warning( disable : 4244 )
#pragma warning( disable : 4305 )
#endif
//------------------------------------------------------------------------------
// windower_class - pointer to this object's definition
//------------------------------------------------------------------------------
t_class* windower_class;
//------------------------------------------------------------------------------
// WINDOW_ID - enumerated window names
//------------------------------------------------------------------------------
enum WINDOW_ID
{
RECTANGLE,
HANN,
HAMMING,
TUKEY,
COSINE,
LANCZOS,
TRIANGLE,
GAUSSIAN,
BARTLETT_HANN,
KAISER,
NUTTALL,
BLACKMAN,
BLACKMAN_HARRIS,
BLACKMAN_NUTTALL,
POISSON,
HANN_POISSON
};
//------------------------------------------------------------------------------
// windower - data structure holding this object's data
//------------------------------------------------------------------------------
typedef struct windower
{
// this object - must always be first variable in struct
t_object object;
// id of the window to write
t_int window_id;
// name of the window to write
t_float* window;
// name of the array being written into
t_symbol* array_name;
// size of the array being written into
t_int array_size;
// tukey window coefficient
t_float tukey_coeff;
// gaussian window coefficient
t_float gaussian_coeff;
// blackman window coefficient
t_float blackman_coeff;
// kaiser window coefficient
t_float kaiser_coeff;
// poisson window coefficient
t_float poisson_coeff;
// hann-poisson window coefficient
t_float hann_poisson_coeff;
} t_windower;
//------------------------------------------------------------------------------
// function prototypes
//------------------------------------------------------------------------------
static void windower_fill_array ( t_windower* object );
void windower_message_parse ( t_windower* object, t_symbol* selector, t_int items, t_atom* list );
void windower_bang ( t_windower* object );
static void* windower_new ( t_symbol* selector, t_int items, t_atom* list );
void windower_setup ( void );
//------------------------------------------------------------------------------
// windower_fill_array - fills the associated array with the current window type
//------------------------------------------------------------------------------
static void windower_fill_array( t_windower* object )
{
// array pointer
t_garray* array;
// array data pointer
t_word* array_data;
// array size
int array_size;
// array error checking flag
t_int valid_array;
// array size
t_float N;
// window function iterator
t_float n;
// array index iterator
t_int index;
// array value pointer
t_float* value;
// temp variables for window function calculation
t_float a, a0, a1, a2, a3, temp;
// check to make sure windower has an array name to work with
//--------------------------------------------------------------------------
if( object->array_name == NULL )
{
pd_error( object, "windower: no array name set" );
return;
}
// check to make sure the array exists
//--------------------------------------------------------------------------
array = ( t_garray* )pd_findbyclass( object->array_name, garray_class );
if( array == NULL )
{
pd_error( object, "windower: %s: no such array", object->array_name->s_name );
return;
}
// check to make sure the array is valid
//--------------------------------------------------------------------------
valid_array = garray_getfloatwords( array, &array_size, &array_data );
if( valid_array == 0 )
{
pd_error( object, "windower: %s: bad template for windower", object->array_name->s_name );
return;
}
// save array size into N for easy reading in the window formulae
N = array_size;
// iterate through the array
for( index = 0 ; index < N ; ++index )
{
// assign index to n instead of typecasting index to float for easier reading in formulae
n = index;
// assign w_float element address to value for easier reading in formulae
value = &( array_data[ index ].w_float );
// calculate window values based on window_id
switch( object->window_id )
{
// rectangle
//------------------------------------------------------------------
case RECTANGLE : *value = 1;
break;
// hann
//------------------------------------------------------------------
case HANN : *value = 0.5 * ( 1 - Cosine( ( C_2_PI * n ) / ( N - 1 ) ) );
break;
// hamming
//------------------------------------------------------------------
case HAMMING : *value = 0.54 - 0.46 * Cosine( ( C_2_PI * n ) / ( N - 1 ) );
break;
// tukey
//------------------------------------------------------------------
case TUKEY : a = object->tukey_coeff;
if( ( n >= 0 ) && ( n <= ( ( a * ( N - 1 ) ) / 2 ) ) )
{
*value = 0.5 * ( 1 + Cosine( C_PI * ( ( ( 2 * n ) / ( a * ( N - 1 ) ) ) - 1 ) ) );
}
else if( ( n >= ( ( a * ( N - 1 ) ) / 2 ) ) && ( n <= ( ( N - 1 ) * ( 1 - ( a / 2 ) ) ) ) )
{
*value = 1;
}
else if( ( n >= ( ( N - 1 ) * ( 1 - ( a / 2 ) ) ) ) && ( n <= ( N - 1 ) ) )
{
*value = 0.5 * ( 1 + Cosine( C_PI * ( ( ( 2 * n ) / ( a * ( N - 1 ) ) ) - ( 2 / a ) + 1 ) ) );
}
break;
// cosine
//------------------------------------------------------------------
case COSINE : *value = Cosine( ( ( C_PI * n ) / ( N - 1 ) ) - C_PI_OVER_2 );
break;
// lanczos
//------------------------------------------------------------------
case LANCZOS : temp = ( ( 2 * n ) / ( N - 1 ) ) - 1;
temp = ( temp == 0 ? C_FLOAT_MIN : temp );
*value = NormalizedSinc( temp );
break;
// triangle
//------------------------------------------------------------------
case TRIANGLE : *value = ( 2 / ( N - 1 ) ) * ( ( ( N - 1 ) / 2 ) - Absolute( n - ( ( N - 1 ) / 2 ) ) );
break;
// gaussian
//------------------------------------------------------------------
case GAUSSIAN : a = object->gaussian_coeff;
*value = Power( C_E, ( -0.5 * Power( ( ( n - ( ( N - 1 ) / 2 ) ) / ( a * ( ( N - 1 ) / 2 ) ) ), 2 ) ) );
break;
// bartlett-hann
//------------------------------------------------------------------
case BARTLETT_HANN : *value = 0.62 - 0.48 * Absolute( n / ( N - 1 ) - 0.5 ) - 0.38 * Cosine( ( C_2_PI * n ) / ( N - 1 ) );
break;
// blackman
//------------------------------------------------------------------
case BLACKMAN : a0 = ( 1 - object->blackman_coeff ) * 0.5;
a1 = 0.5;
a2 = object->blackman_coeff * 0.5;
*value = a0 - a1 * Cosine( ( C_2_PI * n ) / ( N - 1 ) ) + a2 * Cosine( ( C_4_PI * n ) / ( N - 1 ) );
break;
// kaiser
//------------------------------------------------------------------
case KAISER : a = object->kaiser_coeff;
*value = BesselI0( C_PI * a * SquareRoot( 1 - Power( ( ( 2 * n ) / ( N - 1 ) - 1 ), 2 ) ) ) / BesselI0( C_PI * a );
break;
// nuttall
//------------------------------------------------------------------
case NUTTALL : a0 = 0.355768;
a1 = 0.487396;
a2 = 0.144232;
a3 = 0.012604;
*value = a0 - a1 * Cosine( ( C_2_PI * n ) / ( N - 1 ) ) + a2 * Cosine( ( C_4_PI * n ) / ( N - 1 ) ) - a3 * Cosine( ( C_6_PI * n ) / ( N - 1 ) );
break;
// blackman-harris
//------------------------------------------------------------------
case BLACKMAN_HARRIS : a0 = 0.35875;
a1 = 0.48829;
a2 = 0.14128;
a3 = 0.01168;
*value = a0 - a1 * Cosine( ( C_2_PI * n ) / ( N - 1 ) ) + a2 * Cosine( ( C_4_PI * n ) / ( N - 1 ) ) - a3 * Cosine( ( C_6_PI * n ) / ( N - 1 ) );
break;
// blackman-nuttall
//------------------------------------------------------------------
case BLACKMAN_NUTTALL : a0 = 0.3635819;
a1 = 0.4891775;
a2 = 0.1365995;
a3 = 0.0106411;
*value = a0 - a1 * Cosine( ( C_2_PI * n ) / ( N - 1 ) ) + a2 * Cosine( ( C_4_PI * n ) / ( N - 1 ) ) - a3 * Cosine( ( C_6_PI * n ) / ( N - 1 ) );
break;
// poisson
//------------------------------------------------------------------
case POISSON : a = object->poisson_coeff;
*value = Power( C_E, -Absolute( n - ( N - 1 ) / 2) * ( 1 / ( ( N - 1 ) / ( 2 * a ) ) ) );
break;
// hann-poisson
//------------------------------------------------------------------
case HANN_POISSON : a = object->hann_poisson_coeff;
*value = ( 0.5 * ( 1 - Cosine( ( C_2_PI * n ) / ( N - 1 ) ) ) ) * Power( C_E, -Absolute( n - ( N - 1 ) / 2) * ( 1 / ( ( N - 1 ) / ( 2 * a ) ) ) );
break;
// end window calculation
//------------------------------------------------------------------
}
}
garray_redraw( array );
}
//------------------------------------------------------------------------------
// windower_messge_parse - evaluates messages and sets window calculation variables
//------------------------------------------------------------------------------
void windower_message_parse( t_windower* object, t_symbol* selector, t_int items, t_atom* list )
{
// get selector string
const char* message = selector->s_name;
// set ( accepts one argument specifying array name )
//--------------------------------------------------------------------------
if( StringMatch( message, "set" ) )
{
if( list[ 0 ].a_type == A_SYMBOL )
{
// get array name string from list item 0
object->array_name = list[ 0 ].a_w.w_symbol;
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: set: extra arguments ignored" );
}
}
else
{
pd_error( object, "windower: set: invalid argument type" );
}
// skip windower_bang() at the end of this function
return;
}
// rectangle
//--------------------------------------------------------------------------
if( StringMatch( message, "rectangle" ) )
{
object->window_id = RECTANGLE;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: rectangle: extra arguments ignored" );
}
}
// hann
//--------------------------------------------------------------------------
if( StringMatch( message, "hann" ) )
{
object->window_id = HANN;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: hann: extra arguments ignored" );
}
}
// hanning ( hann )
//--------------------------------------------------------------------------
if( StringMatch( message, "hanning" ) )
{
object->window_id = HANN;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: hanning: extra arguments ignored" );
}
}
// hamming
//--------------------------------------------------------------------------
if( StringMatch( message, "hamming" ) )
{
object->window_id = HAMMING;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: hamming: extra arguments ignored" );
}
}
// tukey ( accepts one argument specifying window shape )
//--------------------------------------------------------------------------
if( StringMatch( message, "tukey" ) )
{
object->window_id = TUKEY;
// set coefficient
if( items == 0 )
{
// default value
object->tukey_coeff = 0.5;
}
else if( items > 0 )
{
// get float value from list item 0
object->tukey_coeff = list[ 0 ].a_w.w_float;
// constrain value between 0 and 1
object->tukey_coeff = Clip( object->tukey_coeff, C_FLOAT_MIN, 1 );
}
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: tukey: extra arguments ignored" );
}
}
// cosine
//--------------------------------------------------------------------------
if( StringMatch( message, "cosine" ) )
{
object->window_id = COSINE;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: cosine: extra arguments ignored" );
}
}
// sine ( cosine )
//--------------------------------------------------------------------------
if( StringMatch( message, "sine" ) )
{
object->window_id = COSINE;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: sine: extra arguments ignored" );
}
}
// lanczos
//--------------------------------------------------------------------------
if( StringMatch( message, "lanczos" ) )
{
object->window_id = LANCZOS;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: lanczos: extra arguments ignored" );
}
}
// triangle
//--------------------------------------------------------------------------
if( StringMatch( message, "triangle" ) )
{
object->window_id = TRIANGLE;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: triangle: extra arguments ignored" );
}
}
// bartlett ( triangle )
//--------------------------------------------------------------------------
if( StringMatch( message, "bartlett" ) )
{
object->window_id = TRIANGLE;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: bartlett: extra arguments ignored" );
}
}
// gaussian ( accepts one argument specifying window shape )
//--------------------------------------------------------------------------
if( StringMatch( message, "gaussian" ) )
{
object->window_id = GAUSSIAN;
// set coefficient
if( items == 0 )
{
// default value
object->gaussian_coeff = 0.25;
}
else if( items > 0 )
{
// get float value from list item 0
object->gaussian_coeff = list[ 0 ].a_w.w_float;
// constrain value between 0.0...01 and 1
object->gaussian_coeff = Clip( object->gaussian_coeff, C_FLOAT_MIN, 0.5 );
}
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: gaussian: extra arguments ignored" );
}
}
// bartlett-hann
//--------------------------------------------------------------------------
if( StringMatch( message, "bartlett-hann" ) )
{
object->window_id = BARTLETT_HANN;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: bartlett-hann: extra arguments ignored" );
}
}
// blackman ( accepts one argument specifying window shape )
//--------------------------------------------------------------------------
if( StringMatch( message, "blackman" ) )
{
object->window_id = BLACKMAN;
// set coefficient
if( items == 0 )
{
// default value
object->blackman_coeff = 0.16;
}
else if( items > 0 )
{
// get float value from list item 0
object->blackman_coeff = list[ 0 ].a_w.w_float;
// constrain value between 0 and 1
object->blackman_coeff = Clip( object->blackman_coeff, 0, 0.25 );
}
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: blackman: extra arguments ignored" );
}
}
// kaiser ( accepts one argument specifying window shape )
//--------------------------------------------------------------------------
if( StringMatch( message, "kaiser" ) )
{
object->window_id = KAISER;
// set coefficient
if( items == 0 )
{
// default value
object->kaiser_coeff = 3;
}
else if( items > 0 )
{
// get float value from list item 0
object->kaiser_coeff = list[ 0 ].a_w.w_float;
// constrain value between 2/3 and 4.75
object->kaiser_coeff = Clip( object->kaiser_coeff, 0.666666, 4.75);
}
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: kaiser: extra arguments ignored" );
}
}
// nuttall
//--------------------------------------------------------------------------
if( StringMatch( message, "nuttall" ) )
{
object->window_id = NUTTALL;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: nuttall: extra arguments ignored" );
}
}
// blackman-harris
//--------------------------------------------------------------------------
if( StringMatch( message, "blackman-harris" ) )
{
object->window_id = BLACKMAN_HARRIS;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: blackman-harris: extra arguments ignored" );
}
}
// blackman-nuttall
//--------------------------------------------------------------------------
if( StringMatch( message, "blackman-nuttall" ) )
{
object->window_id = BLACKMAN_NUTTALL;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: blackman-nuttall: extra arguments ignored" );
}
}
// poisson ( accepts one argument specifying window shape )
//--------------------------------------------------------------------------
if( StringMatch( message, "poisson" ) )
{
object->window_id = POISSON;
// set coefficient
if( items == 0 )
{
// default value
object->poisson_coeff = 1;
}
else if( items > 0 )
{
// get float value from list item 0
object->poisson_coeff = list[ 0 ].a_w.w_float;
// constrain value between 0 and max float
object->poisson_coeff = Clip( object->poisson_coeff, 0, C_FLOAT_MAX);
}
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: poisson: extra arguments ignored" );
}
}
// hann-poisson ( accepts one argument specifying window shape )
//--------------------------------------------------------------------------
if( StringMatch( message, "hann-poisson" ) )
{
object->window_id = HANN_POISSON;
// set coefficient
if( items == 0 )
{
// default value
object->hann_poisson_coeff = 1;
}
else if( items > 0 )
{
// get float value from list item 0
object->hann_poisson_coeff = list[ 0 ].a_w.w_float;
// constrain value between 0 and max float
object->hann_poisson_coeff = Clip( object->hann_poisson_coeff, 0, C_FLOAT_MAX);
}
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: hann-poisson: extra arguments ignored" );
}
}
// end message parsing
//--------------------------------------------------------------------------
windower_bang( object );
}
//------------------------------------------------------------------------------
// windower_bang - causes status windower output
//------------------------------------------------------------------------------
void windower_bang( t_windower* object )
{
windower_fill_array( object );
}
//------------------------------------------------------------------------------
// windower_new - initialize the object upon instantiation ( aka "constructor" )
//------------------------------------------------------------------------------
static void* windower_new( t_symbol* selector, t_int items, t_atom* list )
{
// declare a pointer to this class
t_windower* object;
// generate a new object and save its pointer in "object"
object = ( t_windower* )pd_new( windower_class );
t_symbol init_selector;
t_atom init_list;
// parse initialization arguments
//--------------------------------------------------------------------------
// array name
if( items > 0 )
{
// make a "selector" symbol from 'set'
init_selector.s_name = "set";
// make a list of arguments from list argument 0's symbol
init_list.a_w.w_symbol = list[ 0 ].a_w.w_symbol;
init_list.a_type = list[ 0 ].a_type;
// initialize with constructed messages
windower_message_parse( object, &init_selector, 1, &init_list );
}
// window + argument
if( items > 2 )
{
if( ( list[ 1 ].a_type == A_SYMBOL ) && ( list[ 2 ].a_type == A_FLOAT ) )
{
// make a "selector" symbol from list argument 1's name
init_selector.s_name = list[ 1 ].a_w.w_symbol->s_name;
// make a list of arguments from list argument 2's float
init_list.a_w.w_float = list[ 2 ].a_w.w_float;
// initialize with constructed messages
windower_message_parse( object, &init_selector, 1, &init_list );
}
else if( list[ 1 ].a_type == A_SYMBOL )
{
// make a "selector" symbol from list argument 1's name
init_selector.s_name = list[ 1 ].a_w.w_symbol->s_name;
// initialize with constructed messages
windower_message_parse( object, &init_selector, 0, &init_list );
}
else
{
// notify of invalid arguments
pd_error( object, "windower: initalization: invalid arguments" );
}
}
else if( items > 1 )
{
if( list[ 1 ].a_type == A_SYMBOL )
{
// make a "selector symbol from list argument 1's name
init_selector.s_name = list[ 1 ].a_w.w_symbol->s_name;
// initialize with constructed messages
windower_message_parse( object, &init_selector, 0, &init_list );
}
else
{
// notify of invalid arguments
pd_error( object, "windower: initalization: invalid arguments" );
}
}
if( items > 3 )
{
// notify of extra arguments
pd_error( object, "windower: initalization: extra arguments ignored" );
}
// return the pointer to this class
return ( void* )object;
}
//------------------------------------------------------------------------------
// windower setup - defines this object and its properties to Pd
//------------------------------------------------------------------------------
void windower_setup( void )
{
// create a new class and assign its pointer to windower_class
windower_class = class_new( gensym( "windower" ), ( t_newmethod )windower_new, 0, sizeof( t_windower ), 0, A_GIMME, 0 );
// add message handlers
class_addmethod( windower_class, ( t_method )windower_message_parse, gensym( "anything" ), A_GIMME, 0 );
// add bang handler
class_addbang( windower_class, ( t_method )windower_bang );
}
//------------------------------------------------------------------------------
// EOF
//------------------------------------------------------------------------------
// Pd Spectral Toolkit
//
// windower.c
//
// Writes window functions into Pd arrays
//
// Created by Cooper Baker on 5/8/12.
// Updated for 64 Bit Support in September 2019.
// Copyright (C) 2019 Cooper Baker. All Rights Reserved.
//-------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// m_pd.h - main header for Pd
//------------------------------------------------------------------------------
// main header for pd
#include "m_pd.h"
// utility header for Pd Spectral Toolkit project
#include "utility.h"
// disable compiler warnings on windows
#ifdef NT
#pragma warning( disable : 4244 )
#pragma warning( disable : 4305 )
#endif
//------------------------------------------------------------------------------
// windower_class - pointer to this object's definition
//------------------------------------------------------------------------------
t_class* windower_class;
//------------------------------------------------------------------------------
// WINDOW_ID - enumerated window names
//------------------------------------------------------------------------------
enum WINDOW_ID
{
RECTANGLE,
HANN,
HAMMING,
TUKEY,
COSINE,
LANCZOS,
TRIANGLE,
GAUSSIAN,
BARTLETT_HANN,
KAISER,
NUTTALL,
BLACKMAN,
BLACKMAN_HARRIS,
BLACKMAN_NUTTALL,
POISSON,
HANN_POISSON
};
//------------------------------------------------------------------------------
// windower - data structure holding this object's data
//------------------------------------------------------------------------------
typedef struct windower
{
// this object - must always be first variable in struct
t_object object;
// id of the window to write
t_int window_id;
// name of the window to write
t_float* window;
// name of the array being written into
t_symbol* array_name;
// size of the array being written into
t_int array_size;
// tukey window coefficient
t_float tukey_coeff;
// gaussian window coefficient
t_float gaussian_coeff;
// blackman window coefficient
t_float blackman_coeff;
// kaiser window coefficient
t_float kaiser_coeff;
// poisson window coefficient
t_float poisson_coeff;
// hann-poisson window coefficient
t_float hann_poisson_coeff;
} t_windower;
//------------------------------------------------------------------------------
// function prototypes
//------------------------------------------------------------------------------
static void windower_fill_array ( t_windower* object );
void windower_message_parse ( t_windower* object, t_symbol* selector, t_int items, t_atom* list );
void windower_bang ( t_windower* object );
static void* windower_new ( t_symbol* selector, t_int items, t_atom* list );
void windower_setup ( void );
//------------------------------------------------------------------------------
// windower_fill_array - fills the associated array with the current window type
//------------------------------------------------------------------------------
static void windower_fill_array( t_windower* object )
{
// array pointer
t_garray* array;
// array data pointer
t_word* array_data;
// array size
int array_size;
// array error checking flag
t_int valid_array;
// array size
t_float N;
// window function iterator
t_float n;
// array index iterator
t_int index;
// array value pointer
t_float* value;
// temp variables for window function calculation
t_float a, a0, a1, a2, a3, temp;
// check to make sure windower has an array name to work with
//--------------------------------------------------------------------------
if( object->array_name == NULL )
{
pd_error( object, "windower: no array name set" );
return;
}
// check to make sure the array exists
//--------------------------------------------------------------------------
array = ( t_garray* )pd_findbyclass( object->array_name, garray_class );
if( array == NULL )
{
pd_error( object, "windower: %s: no such array", object->array_name->s_name );
return;
}
// check to make sure the array is valid
//--------------------------------------------------------------------------
valid_array = garray_getfloatwords( array, &array_size, &array_data );
if( valid_array == 0 )
{
pd_error( object, "windower: %s: bad template for windower", object->array_name->s_name );
return;
}
// save array size into N for easy reading in the window formulae
N = array_size;
// iterate through the array
for( index = 0 ; index < N ; ++index )
{
// assign index to n instead of typecasting index to float for easier reading in formulae
n = index;
// assign w_float element address to value for easier reading in formulae
value = &( array_data[ index ].w_float );
// calculate window values based on window_id
switch( object->window_id )
{
// rectangle
//------------------------------------------------------------------
case RECTANGLE : *value = 1;
break;
// hann
//------------------------------------------------------------------
case HANN : *value = 0.5 * ( 1 - Cosine( ( C_2_PI * n ) / ( N - 1 ) ) );
break;
// hamming
//------------------------------------------------------------------
case HAMMING : *value = 0.54 - 0.46 * Cosine( ( C_2_PI * n ) / ( N - 1 ) );
break;
// tukey
//------------------------------------------------------------------
case TUKEY : a = object->tukey_coeff;
if( ( n >= 0 ) && ( n <= ( ( a * ( N - 1 ) ) / 2 ) ) )
{
*value = 0.5 * ( 1 + Cosine( C_PI * ( ( ( 2 * n ) / ( a * ( N - 1 ) ) ) - 1 ) ) );
}
else if( ( n >= ( ( a * ( N - 1 ) ) / 2 ) ) && ( n <= ( ( N - 1 ) * ( 1 - ( a / 2 ) ) ) ) )
{
*value = 1;
}
else if( ( n >= ( ( N - 1 ) * ( 1 - ( a / 2 ) ) ) ) && ( n <= ( N - 1 ) ) )
{
*value = 0.5 * ( 1 + Cosine( C_PI * ( ( ( 2 * n ) / ( a * ( N - 1 ) ) ) - ( 2 / a ) + 1 ) ) );
}
break;
// cosine
//------------------------------------------------------------------
case COSINE : *value = Cosine( ( ( C_PI * n ) / ( N - 1 ) ) - C_PI_OVER_2 );
break;
// lanczos
//------------------------------------------------------------------
case LANCZOS : temp = ( ( 2 * n ) / ( N - 1 ) ) - 1;
temp = ( temp == 0 ? C_FLOAT_MIN : temp );
*value = NormalizedSinc( temp );
break;
// triangle
//------------------------------------------------------------------
case TRIANGLE : *value = ( 2 / ( N - 1 ) ) * ( ( ( N - 1 ) / 2 ) - Absolute( n - ( ( N - 1 ) / 2 ) ) );
break;
// gaussian
//------------------------------------------------------------------
case GAUSSIAN : a = object->gaussian_coeff;
*value = Power( C_E, ( -0.5 * Power( ( ( n - ( ( N - 1 ) / 2 ) ) / ( a * ( ( N - 1 ) / 2 ) ) ), 2 ) ) );
break;
// bartlett-hann
//------------------------------------------------------------------
case BARTLETT_HANN : *value = 0.62 - 0.48 * Absolute( n / ( N - 1 ) - 0.5 ) - 0.38 * Cosine( ( C_2_PI * n ) / ( N - 1 ) );
break;
// blackman
//------------------------------------------------------------------
case BLACKMAN : a0 = ( 1 - object->blackman_coeff ) * 0.5;
a1 = 0.5;
a2 = object->blackman_coeff * 0.5;
*value = a0 - a1 * Cosine( ( C_2_PI * n ) / ( N - 1 ) ) + a2 * Cosine( ( C_4_PI * n ) / ( N - 1 ) );
break;
// kaiser
//------------------------------------------------------------------
case KAISER : a = object->kaiser_coeff;
*value = BesselI0( C_PI * a * SquareRoot( 1 - Power( ( ( 2 * n ) / ( N - 1 ) - 1 ), 2 ) ) ) / BesselI0( C_PI * a );
break;
// nuttall
//------------------------------------------------------------------
case NUTTALL : a0 = 0.355768;
a1 = 0.487396;
a2 = 0.144232;
a3 = 0.012604;
*value = a0 - a1 * Cosine( ( C_2_PI * n ) / ( N - 1 ) ) + a2 * Cosine( ( C_4_PI * n ) / ( N - 1 ) ) - a3 * Cosine( ( C_6_PI * n ) / ( N - 1 ) );
break;
// blackman-harris
//------------------------------------------------------------------
case BLACKMAN_HARRIS : a0 = 0.35875;
a1 = 0.48829;
a2 = 0.14128;
a3 = 0.01168;
*value = a0 - a1 * Cosine( ( C_2_PI * n ) / ( N - 1 ) ) + a2 * Cosine( ( C_4_PI * n ) / ( N - 1 ) ) - a3 * Cosine( ( C_6_PI * n ) / ( N - 1 ) );
break;
// blackman-nuttall
//------------------------------------------------------------------
case BLACKMAN_NUTTALL : a0 = 0.3635819;
a1 = 0.4891775;
a2 = 0.1365995;
a3 = 0.0106411;
*value = a0 - a1 * Cosine( ( C_2_PI * n ) / ( N - 1 ) ) + a2 * Cosine( ( C_4_PI * n ) / ( N - 1 ) ) - a3 * Cosine( ( C_6_PI * n ) / ( N - 1 ) );
break;
// poisson
//------------------------------------------------------------------
case POISSON : a = object->poisson_coeff;
*value = Power( C_E, -Absolute( n - ( N - 1 ) / 2) * ( 1 / ( ( N - 1 ) / ( 2 * a ) ) ) );
break;
// hann-poisson
//------------------------------------------------------------------
case HANN_POISSON : a = object->hann_poisson_coeff;
*value = ( 0.5 * ( 1 - Cosine( ( C_2_PI * n ) / ( N - 1 ) ) ) ) * Power( C_E, -Absolute( n - ( N - 1 ) / 2) * ( 1 / ( ( N - 1 ) / ( 2 * a ) ) ) );
break;
// end window calculation
//------------------------------------------------------------------
}
}
garray_redraw( array );
}
//------------------------------------------------------------------------------
// windower_messge_parse - evaluates messages and sets window calculation variables
//------------------------------------------------------------------------------
void windower_message_parse( t_windower* object, t_symbol* selector, t_int items, t_atom* list )
{
// get selector string
const char* message = selector->s_name;
// set ( accepts one argument specifying array name )
//--------------------------------------------------------------------------
if( StringMatch( message, "set" ) )
{
if( list[ 0 ].a_type == A_SYMBOL )
{
// get array name string from list item 0
object->array_name = list[ 0 ].a_w.w_symbol;
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: set: extra arguments ignored" );
}
}
else
{
pd_error( object, "windower: set: invalid argument type" );
}
// skip windower_bang() at the end of this function
return;
}
// rectangle
//--------------------------------------------------------------------------
if( StringMatch( message, "rectangle" ) )
{
object->window_id = RECTANGLE;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: rectangle: extra arguments ignored" );
}
}
// hann
//--------------------------------------------------------------------------
if( StringMatch( message, "hann" ) )
{
object->window_id = HANN;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: hann: extra arguments ignored" );
}
}
// hanning ( hann )
//--------------------------------------------------------------------------
if( StringMatch( message, "hanning" ) )
{
object->window_id = HANN;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: hanning: extra arguments ignored" );
}
}
// hamming
//--------------------------------------------------------------------------
if( StringMatch( message, "hamming" ) )
{
object->window_id = HAMMING;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: hamming: extra arguments ignored" );
}
}
// tukey ( accepts one argument specifying window shape )
//--------------------------------------------------------------------------
if( StringMatch( message, "tukey" ) )
{
object->window_id = TUKEY;
// set coefficient
if( items == 0 )
{
// default value
object->tukey_coeff = 0.5;
}
else if( items > 0 )
{
// get float value from list item 0
object->tukey_coeff = list[ 0 ].a_w.w_float;
// constrain value between 0 and 1
object->tukey_coeff = Clip( object->tukey_coeff, C_FLOAT_MIN, 1 );
}
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: tukey: extra arguments ignored" );
}
}
// cosine
//--------------------------------------------------------------------------
if( StringMatch( message, "cosine" ) )
{
object->window_id = COSINE;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: cosine: extra arguments ignored" );
}
}
// sine ( cosine )
//--------------------------------------------------------------------------
if( StringMatch( message, "sine" ) )
{
object->window_id = COSINE;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: sine: extra arguments ignored" );
}
}
// lanczos
//--------------------------------------------------------------------------
if( StringMatch( message, "lanczos" ) )
{
object->window_id = LANCZOS;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: lanczos: extra arguments ignored" );
}
}
// triangle
//--------------------------------------------------------------------------
if( StringMatch( message, "triangle" ) )
{
object->window_id = TRIANGLE;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: triangle: extra arguments ignored" );
}
}
// bartlett ( triangle )
//--------------------------------------------------------------------------
if( StringMatch( message, "bartlett" ) )
{
object->window_id = TRIANGLE;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: bartlett: extra arguments ignored" );
}
}
// gaussian ( accepts one argument specifying window shape )
//--------------------------------------------------------------------------
if( StringMatch( message, "gaussian" ) )
{
object->window_id = GAUSSIAN;
// set coefficient
if( items == 0 )
{
// default value
object->gaussian_coeff = 0.25;
}
else if( items > 0 )
{
// get float value from list item 0
object->gaussian_coeff = list[ 0 ].a_w.w_float;
// constrain value between 0.0...01 and 1
object->gaussian_coeff = Clip( object->gaussian_coeff, C_FLOAT_MIN, 0.5 );
}
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: gaussian: extra arguments ignored" );
}
}
// bartlett-hann
//--------------------------------------------------------------------------
if( StringMatch( message, "bartlett-hann" ) )
{
object->window_id = BARTLETT_HANN;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: bartlett-hann: extra arguments ignored" );
}
}
// blackman ( accepts one argument specifying window shape )
//--------------------------------------------------------------------------
if( StringMatch( message, "blackman" ) )
{
object->window_id = BLACKMAN;
// set coefficient
if( items == 0 )
{
// default value
object->blackman_coeff = 0.16;
}
else if( items > 0 )
{
// get float value from list item 0
object->blackman_coeff = list[ 0 ].a_w.w_float;
// constrain value between 0 and 1
object->blackman_coeff = Clip( object->blackman_coeff, 0, 0.25 );
}
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: blackman: extra arguments ignored" );
}
}
// kaiser ( accepts one argument specifying window shape )
//--------------------------------------------------------------------------
if( StringMatch( message, "kaiser" ) )
{
object->window_id = KAISER;
// set coefficient
if( items == 0 )
{
// default value
object->kaiser_coeff = 3;
}
else if( items > 0 )
{
// get float value from list item 0
object->kaiser_coeff = list[ 0 ].a_w.w_float;
// constrain value between 2/3 and 4.75
object->kaiser_coeff = Clip( object->kaiser_coeff, 0.666666, 4.75);
}
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: kaiser: extra arguments ignored" );
}
}
// nuttall
//--------------------------------------------------------------------------
if( StringMatch( message, "nuttall" ) )
{
object->window_id = NUTTALL;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: nuttall: extra arguments ignored" );
}
}
// blackman-harris
//--------------------------------------------------------------------------
if( StringMatch( message, "blackman-harris" ) )
{
object->window_id = BLACKMAN_HARRIS;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: blackman-harris: extra arguments ignored" );
}
}
// blackman-nuttall
//--------------------------------------------------------------------------
if( StringMatch( message, "blackman-nuttall" ) )
{
object->window_id = BLACKMAN_NUTTALL;
// notify of extra arguments
if( items > 0 )
{
pd_error( object, "windower: blackman-nuttall: extra arguments ignored" );
}
}
// poisson ( accepts one argument specifying window shape )
//--------------------------------------------------------------------------
if( StringMatch( message, "poisson" ) )
{
object->window_id = POISSON;
// set coefficient
if( items == 0 )
{
// default value
object->poisson_coeff = 1;
}
else if( items > 0 )
{
// get float value from list item 0
object->poisson_coeff = list[ 0 ].a_w.w_float;
// constrain value between 0 and max float
object->poisson_coeff = Clip( object->poisson_coeff, 0, C_FLOAT_MAX);
}
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: poisson: extra arguments ignored" );
}
}
// hann-poisson ( accepts one argument specifying window shape )
//--------------------------------------------------------------------------
if( StringMatch( message, "hann-poisson" ) )
{
object->window_id = HANN_POISSON;
// set coefficient
if( items == 0 )
{
// default value
object->hann_poisson_coeff = 1;
}
else if( items > 0 )
{
// get float value from list item 0
object->hann_poisson_coeff = list[ 0 ].a_w.w_float;
// constrain value between 0 and max float
object->hann_poisson_coeff = Clip( object->hann_poisson_coeff, 0, C_FLOAT_MAX);
}
// notify of extra arguments
if( items > 1 )
{
pd_error( object, "windower: hann-poisson: extra arguments ignored" );
}
}
// end message parsing
//--------------------------------------------------------------------------
windower_bang( object );
}
//------------------------------------------------------------------------------
// windower_bang - causes status windower output
//------------------------------------------------------------------------------
void windower_bang( t_windower* object )
{
windower_fill_array( object );
}
//------------------------------------------------------------------------------
// windower_new - initialize the object upon instantiation ( aka "constructor" )
//------------------------------------------------------------------------------
static void* windower_new( t_symbol* selector, t_int items, t_atom* list )
{
// declare a pointer to this class
t_windower* object;
// generate a new object and save its pointer in "object"
object = ( t_windower* )pd_new( windower_class );
t_symbol init_selector;
t_atom init_list;
// parse initialization arguments
//--------------------------------------------------------------------------
// array name
if( items > 0 )
{
// make a "selector" symbol from 'set'
init_selector.s_name = "set";
// make a list of arguments from list argument 0's symbol
init_list.a_w.w_symbol = list[ 0 ].a_w.w_symbol;
init_list.a_type = list[ 0 ].a_type;
// initialize with constructed messages
windower_message_parse( object, &init_selector, 1, &init_list );
}
// window + argument
if( items > 2 )
{
if( ( list[ 1 ].a_type == A_SYMBOL ) && ( list[ 2 ].a_type == A_FLOAT ) )
{
// make a "selector" symbol from list argument 1's name
init_selector.s_name = list[ 1 ].a_w.w_symbol->s_name;
// make a list of arguments from list argument 2's float
init_list.a_w.w_float = list[ 2 ].a_w.w_float;
// initialize with constructed messages
windower_message_parse( object, &init_selector, 1, &init_list );
}
else if( list[ 1 ].a_type == A_SYMBOL )
{
// make a "selector" symbol from list argument 1's name
init_selector.s_name = list[ 1 ].a_w.w_symbol->s_name;
// initialize with constructed messages
windower_message_parse( object, &init_selector, 0, &init_list );
}
else
{
// notify of invalid arguments
pd_error( object, "windower: initalization: invalid arguments" );
}
}
else if( items > 1 )
{
if( list[ 1 ].a_type == A_SYMBOL )
{
// make a "selector symbol from list argument 1's name
init_selector.s_name = list[ 1 ].a_w.w_symbol->s_name;
// initialize with constructed messages
windower_message_parse( object, &init_selector, 0, &init_list );
}
else
{
// notify of invalid arguments
pd_error( object, "windower: initalization: invalid arguments" );
}
}
if( items > 3 )
{
// notify of extra arguments
pd_error( object, "windower: initalization: extra arguments ignored" );
}
// return the pointer to this class
return ( void* )object;
}
//------------------------------------------------------------------------------
// windower setup - defines this object and its properties to Pd
//------------------------------------------------------------------------------
void windower_setup( void )
{
// create a new class and assign its pointer to windower_class
windower_class = class_new( gensym( "windower" ), ( t_newmethod )windower_new, 0, sizeof( t_windower ), 0, A_GIMME, 0 );
// add message handlers
class_addmethod( windower_class, ( t_method )windower_message_parse, gensym( "anything" ), A_GIMME, 0 );
// add bang handler
class_addbang( windower_class, ( t_method )windower_bang );
}
//------------------------------------------------------------------------------
// EOF
//------------------------------------------------------------------------------