#ifndef WABOR_T_H
#define WABOR_T_H

//Funktionen fuer PD-Externals

#include "wabor_t_definitions.h"
#include "wabor_t_array_functions.h" 
#include "wabor_t_theta_functions.h"

static t_class *pcWabor_t;
struct _sthread_wabor_param;

typedef struct {
	t_object x_obj; //t_object has to be the first entry in the structure!!

	t_float fConstSignal;
	
	//t_inlet *x_in; //Inlet fuer Messages
	
	t_inlet *x_inC; //Intlet fuer Kontrolldaten
	t_outlet *x_outG; //Outlet fuer Gabor Frames
	t_outlet *x_outC; //Outlet fuer Datenweitergabe an iwabor_t
	t_outlet *x_outM; //Outlet fuer Messages
	
	sWabor_Coeff **pawc; //Array of sWabor_Coeff, containts the wabor coefficients
	
	
	sWatom_Param *psParam; 

	t_int iq_analyse_min; 
	t_int iq_analyse_sup; 
	t_int iLongestFrame;
	t_int q_sup;
	
	t_float var;		 //Variable für Debug Zwecke. Mit "set_var" in PD setzbar.

	
	struct { //Array das die gesamte Audiodatei enthaelt.
	    ALIGN16 t_sample *pA; //Pointer auf Ersten Eintrag des Vektors
	    t_sample *pC; //Pointer auf Eintrag wo weiter gespeicher wird
	    t_sample *pE; //Pointer auf eins hinter Ende.
	    t_int iLength, iLengthTemp;  //Laenge des Buffers, Vielfaches von PD_BLOCKSIZE
	    t_int counter; //Zaehlt die Samples durch
	} sSound;
	
	t_int iComputeCoefficients;
        t_int num_threads;
        
        volatile t_int iThreadCount;      
#if defined(WABOR_T_NOTHREADS)
    
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
    CRITICAL_SECTION mutex;
#elif defined(__linux__)
    pthread_mutex_t mutex;
    pthread_t thread_id;       
#else
    
#endif     
	
	struct _sthread_wabor_param *pawp[WABOR_T_MAX_THREADS]; //Used to pass data to the working threads

} sWabor_t;

struct _sthread_wabor_param{
    t_int iCounter;
    t_int itcBin;
    t_int iMin;
    t_int iSup;
    sWabor_t* psW;
} ;
typedef struct _sthread_wabor_param sthread_wabor_param;

void TEST(void);

void wabor_t_set_pointers_to_NULL(sWabor_t *psW);
void wabor_t_set_start_values(sWabor_t *psW);
void *wabor_t_new(t_floatarg fArg); //constructor
void wabor_t_delete(sWabor_t* psWabor_t);
void wabor_t_dsp(sWabor_t *psW, t_signal **sp);
t_int *wabor_t_perform(t_int *aw);
thread_return_type wabor_t_perform_thread( void* _sthread_param );
void wabor_t_bang(sWabor_t const * const psW);

t_int wabor_t_test_compileparam(); //Testet alle Parameter die nicht geaendert werden koennen zur Laufzeit ob sie richtig sind
void wabor_t_test_param(sWabor_t const * const psW); //Testet alle Parameter anderen Parameter ob sie richtig sind

void wabor_t_initialize(sWabor_t* psW);
void wabor_t_initialize_pawc(sWabor_t* psW);
void wabor_t_initialize_pawp(sWabor_t* psW);
void wabor_t_initialize_sSound(sWabor_t* psW);

//void wabor_t_test(sWabor_t *psW, t_float fPrintOut);
t_int wabor_t_test_windows(sWabor_t const * const psW, t_int iPrintOutput);

//t_float* wabor_t_get_sSound(sWabor_t* psW);

//t_int wabor_t_find_longest_frame_paf(sWabor_t const * const psW);
//t_int wabor_t_find_shortest_frame_paf(sWabor_t const * const psW);
//t_int wabor_t_find_longest_frame_pac(sWabor_t const * const psW);
//t_int wabor_t_find_shortest_frame_pac(sWabor_t const * const psW);

void wabor_t_set_compute_coefficients(sWabor_t *psW, t_float fCompute);

//Allgemeine Funktionen
void wabor_t_set_temp_values(sWabor_t *psW);
void wabor_t_set_soundbuffer_length_factor(sWabor_t *psW, t_float fFactor);
void wabor_t_set_q_analyse_min(sWabor_t *psW, t_float qmin);
void wabor_t_set_q_analyse_sup(sWabor_t *psW, t_float qsup);

void wabor_t_set_var(sWabor_t* psW, t_float f);

void wabor_t_set_num_threads(sWabor_t* psW, t_float num);
t_int wabor_t_round_up_to_multiple_of_small_primes(sWabor_t const * const psW, t_float n, t_float maxprime);




#endif //WABOR_T_H


