Beispiel #1
0
// Perform forward FFT of real data
// Accepts:
//   membvars - pointer to struct of FFT variables
//   input - pointer to an array of (real) input values, size nfft
//   output_re - pointer to an array of the real part of the output,
//     size nfft/2 + 1
//   output_im - pointer to an array of the imaginary part of the output,
//     size nfft/2 + 1
void
fft_forward(fft_vars * membvars, float *input, float *output_re,
	    float *output_im)
{
	int ti;
	int nfft;
	int hnfft;
	int numfreqs;

	nfft = membvars->nfft;
	hnfft = nfft / 2;
	numfreqs = membvars->numfreqs;

	for (ti = 0; ti < nfft; ti++) {
		membvars->fft_data[ti] = input[ti];
	}

	mayer_realfft(nfft, membvars->fft_data);

	output_im[0] = 0;
	for (ti = 0; ti < hnfft; ti++) {
		output_re[ti] = membvars->fft_data[ti];
		output_im[ti + 1] = membvars->fft_data[nfft - 1 - ti];
	}
	output_re[hnfft] = membvars->fft_data[hnfft];
	output_im[hnfft] = 0;
}
Beispiel #2
0
YSE::DSP::buffer & YSE::DSP::realFft::operator()(YSE::DSP::buffer & in) {

  if (in.getLength() != real.getLength()) real.resize(in.getLength());
  if (in.getLength() != imaginary.getLength()) imaginary.resize(in.getLength());

  int n = in.getLength();
  int n2 = (n >> 1);

  if (n < 4) {
    assert(false); // minimum length is 4
    return real;
  }

  if (in.getPtr() != real.getPtr()) {
    real = in;
  }
  mayer_realfft(real.getLength(), real.getPtr());
  flip(n2 - 1, real.getPtr() + (n2 + 1), imaginary.getPtr() + n2);
  zero(real.getPtr() + (n2 + 1), ((n2 - 1)&(~7)));
  zero(real.getPtr() + (n2 + 1) + ((n2 - 1)&(~7)), ((n2 - 1) & 7));
  zero(imaginary.getPtr() + n2, n2);
  zero(imaginary.getPtr(), 1);

  return real;
}
Beispiel #3
0
static t_int *sigrfft_perform(t_int *w)
{
    t_sample *in = (t_sample *)(w[1]);
    int n = (int)w[2];
    mayer_realfft(n, in);
    return (w+3);
}
Beispiel #4
0
static void specBrightness_tilde_bang(t_specBrightness_tilde *x)
{
    int i, j, window, window_half, bang_sample, bin_boundary;
    float dividend, divisor, brightness;
    t_sample *signal_R, *signal_I;
	double current_time;

    window = x->window;
    window_half = window*0.5;

	// create local memory
	signal_R = (t_sample *)getbytes(0);
	signal_I = (t_sample *)getbytes(0);
	signal_R = (t_sample *)t_resizebytes(signal_R, 0, window*sizeof(t_sample));
	signal_I = (t_sample *)t_resizebytes(signal_I, 0, window_half*sizeof(t_sample));
	
    bin_boundary = specBrightness_tilde_nearest_bin_index(x->freq_boundary, x->bin_freqs);  // hard-coded based on 1200, but can use nearest_bin_freq function later
    
	current_time = clock_gettimesince(x->last_dsp_time);
	bang_sample = (int)(((current_time/1000.0)*x->sr)+0.5); // round

	if (bang_sample < 0)
        bang_sample = 0;
    else if ( bang_sample >= x->n )
        bang_sample = x->n - 1;
            
	// construct analysis window using bang_sample as the end of the window
	for(i=0, j=bang_sample; i<window; i++, j++)
		signal_R[i] = x->signal_R[j];
	
	specBrightness_tilde_hann(window, signal_R, x->hann);
	mayer_realfft(window, signal_R);
	specBrightness_tilde_realfft_unpack(window, window_half, signal_R, signal_I);
	specBrightness_tilde_abs(window_half, signal_R, signal_I);
	
// 	if(x->normalize)
// 		specBrightness_tilde_normal(window_half, signal_R);

	dividend=0;
	divisor=0;
	brightness=0;
	
	for(i=bin_boundary; i<window_half; i++)
		dividend += signal_R[i];

	for(i=0; i<window_half; i++)
		divisor += signal_R[i];
	
	if(divisor==0)
		divisor=1;
		
	brightness = dividend/divisor;
		
	outlet_float(x->x_brightness, brightness);

	// free local memory
	t_freebytes(signal_R, window * sizeof(t_sample));
	t_freebytes(signal_I, window_half * sizeof(t_sample));
}
Beispiel #5
0
static void specCentroid_tilde_bang(t_specCentroid_tilde *x)
{
    int i, j, window, window_half, bang_sample;
    float dividend, divisor, centroid;
    t_sample *signal_R, *signal_I;
	double current_time;

    window = x->window;
    window_half = window*0.5;

	// create local memory
	signal_R = (t_sample *)getbytes(0);
	signal_I = (t_sample *)getbytes(0);
	signal_R = (t_sample *)t_resizebytes(signal_R, 0, window*sizeof(t_sample));
	signal_I = (t_sample *)t_resizebytes(signal_I, 0, window_half*sizeof(t_sample));
    
	current_time = clock_gettimesince(x->last_dsp_time);
	bang_sample = (int)(((current_time/1000.0)*x->sr)+0.5); // round

	if (bang_sample < 0)
        bang_sample = 0;
    else if ( bang_sample >= x->n )
        bang_sample = x->n - 1;
            
	// construct analysis window using bang_sample as the end of the window
	for(i=0, j=bang_sample; i<window; i++, j++)
		signal_R[i] = x->signal_R[j];
	
	specCentroid_tilde_hann(window, signal_R, x->hann);
	mayer_realfft(window, signal_R);
	specCentroid_tilde_realfft_unpack(window, window_half, signal_R, signal_I);
	specCentroid_tilde_abs(window_half, signal_R, signal_I);
	
// 	if(x->normalize)
// 		specCentroid_tilde_normal(window_half, signal_R);

	dividend=0;
	divisor=0;
	centroid=0;
	
	for(i=0; i<window_half; i++)
		dividend += signal_R[i]*(i*(x->sr/window));  // weight by bin freq

	for(i=0; i<window_half; i++)
		divisor += signal_R[i];
		
	if(divisor==0) divisor = 1; // don't divide by zero
	
	centroid = dividend/divisor;
		
	outlet_float(x->x_centroid, centroid);

	// free local memory
	t_freebytes(signal_R, window * sizeof(t_sample));
	t_freebytes(signal_I, window_half * sizeof(t_sample));
}
Beispiel #6
0
static void cepstrum_tilde_bang(t_cepstrum_tilde *x)
{
    int i, j, window, window_half, bang_sample;
   	t_atom *listOut;
    t_sample *signal_R, *signal_I;
	double current_time;

    window = x->window;
    window_half = window*0.5;

   	signal_R = (t_sample *)getbytes(0);
	signal_I = (t_sample *)getbytes(0);
	listOut = (t_atom *)getbytes(0);
	signal_R = (t_sample *)t_resizebytes(signal_R, 0, window*sizeof(t_sample));
	signal_I = (t_sample *)t_resizebytes(signal_I, 0, window_half*sizeof(t_sample));
	listOut = (t_atom *)t_resizebytes(listOut, 0, ((int)x->window*0.5)*sizeof(t_atom));
	
	current_time = clock_gettimesince(x->last_dsp_time);
	bang_sample = (int)(((current_time/1000.0)*x->sr)+0.5); // round

	if (bang_sample < 0)
        bang_sample = 0;
    else if ( bang_sample >= x->n )
        bang_sample = x->n - 1;
            
	// construct analysis window using bang_sample as the end of the window
	for(i=0, j=bang_sample; i<window; i++, j++)
		signal_R[i] = x->signal_R[j];
	
	cepstrum_tilde_hann(window, signal_R, x->hann);
	mayer_realfft(window, signal_R);
	cepstrum_tilde_realfft_unpack(window, window_half, signal_R, signal_I);
	cepstrum_tilde_abs(window_half, signal_R, signal_I);
	
	if(x->normalize)
		cepstrum_tilde_normal(window_half, signal_R);
	
	cepstrum_tilde_log(window_half, signal_R);

	// fill out the negative frequencies
	for(i=0; i<window_half; i++)
		signal_I[i] = signal_R[i];
//		signal_I[i] = 0.0; // or we could zero them out...
		
	cepstrum_tilde_realifft(window, window_half, signal_R, signal_I);

				
	for(i=0; i<window_half; i++)
		SETFLOAT(listOut+i, signal_R[i]);

	outlet_list(x->x_featureList, 0, window_half, listOut);

	t_freebytes(signal_R, window * sizeof(t_sample));
	t_freebytes(signal_I, window_half * sizeof(t_sample));
	t_freebytes(listOut, window_half * sizeof(t_atom));
}
Beispiel #7
0
static t_int* pod_tilde_perform(t_int* w)
{
    t_pod_tilde *x = (t_pod_tilde *)(w[1]);     // x is the reference to the data struct
    t_sample  *in1 =    (t_sample *)(w[2]);     // in1 is an array of input samples
    int          n =           (int)(w[3]);     // n is the number of samples passed to this function
    
    int size_diff = x->window_size - n;
    
    // This takes part of the signal buffer and shifts it to the front
    for (int i = 0; i < size_diff; i++)
        x->signal[i] = x->signal[i + n];
    
    // This takes the new samples filters them and puts them into the buffer
    for (int i = 0; i < n; i++)
    {
        x->signal[size_diff + i] = pod_tilde_outer_filter(x, in1[i]);
        x->signal[size_diff + i] = pod_tilde_middle_filter(x, x->signal[size_diff + i]);
    }
   
    // Increase the dsp_tick variable by the number of samples passed to callback
    x->dsp_tick += n;
    
    // If the dsp_tick reaches the hop_size value, then we do our processing
    if (x->dsp_tick >= x->hop_size)
    {
        x->dsp_tick = 0;
        
        // do windowing
        for (int i = 0; i < x->window_size; i++)
            x->analysis[i] = x->signal[i] * x->window[i];
        
        // take fft
        mayer_realfft(x->window_size, x->analysis);
        
        // Get the magnitude and assign it to the first half of the analysis buffer
        for (int i = 0; i < x->window_size / 2; i++)
        {
            int i_index = x->window_size - i;
            x->analysis[i] = sqrt((x->analysis[i] * x->analysis[i]) + (x->analysis[i_index] * x->analysis[i_index]));
        }
        
        // multiply analysis buffer by the filterbank
                                                                              
    
    }
        
    return (w + 4);
}
Beispiel #8
0
Var* ff_realfft3(vfuncptr func, Var* arg)
{
	Var* obj = NULL;
	size_t i, n;
	double* in;

	Alist alist[3];
	alist[0]      = make_alist("obj", ID_VAL, NULL, &obj);
	alist[1].name = NULL;

	if (parse_args(func, arg, alist) == 0) return (NULL);

	if (obj == NULL) {
		parse_error("%s: No object specified\n", func->name);
		return (NULL);
	}

	n = V_DSIZE(obj);
	if (n > INT_MAX) {
		parse_error("%s: fft function does not handle objects greater than %ld bytes.\n",
		            func->name, INT_MAX);
		return NULL;
	}

	in = (double*)calloc(n, sizeof(double));
	if (in == NULL) {
		parse_error("%s: Unable to alloc %ld bytes.\n", func->name, n * sizeof(double));
		return NULL;
	}

	for (i = 0; i < n; i++) {
		in[i] = extract_double(obj, i);
	}

	if (func->fdata == (void*)1) {
		mayer_realfft(n, in);
	} else {
		mayer_realifft(n, in);
	}

	return (newVal(BSQ, 1, n, 1, DV_DOUBLE, in));
}
Beispiel #9
0
static void bark_analyze(t_bark *x, t_floatarg startTime, t_floatarg endTime)
{
    int i, j, window, windowHalf, hop, nFrames, frame, sampRange, startSamp, endSamp;
    t_float totalGrowth, totalVel, *windowFuncPtr;
	t_garray *a;

	if(!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
        pd_error(x, "%s: no such array", x->x_arrayname->s_name);
    else if(!garray_getfloatwords(a, &x->x_array_points, &x->x_vec))
    	pd_error(x, "%s: bad template for bark", x->x_arrayname->s_name);
	else
	{
		window = x->window;
		windowHalf = window*0.5;
		hop = x->hop;

		if(endTime)
		{
			startSamp = floor(startTime*x->sr);
			endSamp = floor(endTime*x->sr);

			if(startSamp>=0 && endSamp<x->x_array_points)
				sampRange = endSamp-startSamp+1;
			else
			{
				error("invalid time range");
				return;
			}
		}
		else
		{
			sampRange = x->x_array_points;
			startSamp = 0;
			endSamp = x->x_array_points-1;
		}

		nFrames = floor((sampRange-window)/hop);

		// init mask to zero
		for(i=0; i<x->numFilters; i++)
			x->mask[i] = 0.0;

		for(frame=0; frame<nFrames; frame++)
		{
			// fill buffer with <window> samples
			for(i=0, j=frame*hop+startSamp; i<window; i++, j++)
				x->signalBuf[i] = x->x_vec[j].w_float;

			totalGrowth = 0.0;
			totalVel = 0.0;

		    // set window function
		    windowFuncPtr = x->hann; //default case to get rid of compile warning

		    switch(x->windowFunction)
		    {
			    case 0:
				    break;
			    case 1:
				    windowFuncPtr = x->blackman;
				    break;
			    case 2:
				    windowFuncPtr = x->cosine;
				    break;
			    case 3:
				    windowFuncPtr = x->hamming;
				    break;
			    case 4:
				    windowFuncPtr = x->hann;
				    break;
			    default:
				    break;
		    };

		    // if windowFunction == 0, skip the windowing (rectangular)
		    if(x->windowFunction>0)
			    for(i=0; i<window; i++, windowFuncPtr++)
				    x->analysisBuf[i] = x->signalBuf[i] * *windowFuncPtr;
		    else
			    for(i=0; i<window; i++, windowFuncPtr++)
				    x->analysisBuf[i] = x->signalBuf[i];

			mayer_realfft(window, x->analysisBuf);

			// calculate the power spectrum in place. we'll overwrite the first N/2+1 points in x->analysisBuf with the magnitude spectrum, as this is all that's used below in filterbank_multiply()
			x->analysisBuf[0] = x->analysisBuf[0] * x->analysisBuf[0];  // DC
			x->analysisBuf[windowHalf] = x->analysisBuf[windowHalf] * x->analysisBuf[windowHalf];  // Nyquist

			for(i=(window-1), j=1; i>windowHalf; i--, j++)
				x->analysisBuf[j] = (x->analysisBuf[j]*x->analysisBuf[j]) + (x->analysisBuf[i]*x->analysisBuf[i]);

			// optional use of power/magnitude spectrum
			if(!x->powerSpectrum)
				for(i=0; i<=windowHalf; i++)
					x->analysisBuf[i] = sqrt(x->analysisBuf[i]);

			tIDLib_filterbankMultiply(x->analysisBuf, x->normalize, x->filterAvg, x->x_filterbank, x->numFilters);

			// optional loudness weighting
			if(x->useWeights)
				for(i=0; i<x->numFilters; i++)
					x->analysisBuf[i] *= x->loudWeights[i];

			for(i=0; i<x->numFilters; i++)
				totalVel += x->analysisBuf[i];

			// init growth list to zero
			for(i=0; i<x->numFilters; i++)
				x->growth[i] = 0.0;

			for(i=0; i<x->numFilters; i++)
			{
				// from p.3 of Puckette/Apel/Zicarelli, 1998
				// salt divisor with + 1.0e-15 in case previous power was zero
				if(x->analysisBuf[i] > x->mask[i])
					x->growth[i] = x->analysisBuf[i]/(x->mask[i] + 1.0e-15) - 1.0;

				if(i>=x->loBin && i<=x->hiBin && x->growth[i]>0)
					totalGrowth += x->growth[i];

				SETFLOAT(x->growthList+i, x->growth[i]);
			}

			if(frame*hop+startSamp >= x->debounceActive)
			    x->debounceActive = -1;

			if(totalVel >= x->minvel && totalGrowth > x->hiThresh && !x->haveHit && x->debounceActive < 0)
			{
				if(x->debug)
					post("peak: %f", totalGrowth);

				x->haveHit = 1;
				x->debounceActive = frame*hop+startSamp + x->debounceSamp;
			}
			else if(x->haveHit && x->loThresh>0 && totalGrowth < x->loThresh) // if loThresh is an actual value (not -1), then wait until growth drops below that value before reporting attack
			{
				if(x->debug)
					post("drop: %f", totalGrowth);

				x->haveHit = 0;

				// don't output data if spew will do it anyway below
				if(!x->spew)
				{
					outlet_list(x->x_outputList, 0, x->numFilters, x->growthList);
					outlet_float(x->x_growthOut, totalGrowth);
				}

				// add half a window of samples as a fudge factor. note that since this NRT and we can look into the future, all attack reports will be roughly a half window EARLY.  in RT, everything is a half window LATE because the point of reference is the END of the window.  here, it's the BEGINNING of the window.
				outlet_float(x->x_timeOut, (frame*hop+startSamp + windowHalf)/x->sr);
			}
			else if(x->haveHit && x->loThresh<0 && totalGrowth < x->prevTotalGrowth) // if loThresh == -1, report attack as soon as growth shows any decay at all
			{
				if(x->debug)
					post("drop: %f", totalGrowth);

				x->haveHit = 0;

				// don't output data if spew will do it anyway below
				if(!x->spew)
				{
					outlet_list(x->x_outputList, 0, x->numFilters, x->growthList);
					outlet_float(x->x_growthOut, totalGrowth);
				}

				// add half a window of samples as a fudge factor. note that since this NRT and we can look into the future, all attack reports will be roughly a half window EARLY.  in RT, everything is a half window LATE because the point of reference is the END of the window.  here, it's the BEGINNING of the window.
				outlet_float(x->x_timeOut, (frame*hop+startSamp + windowHalf)/x->sr);
			}

			if(x->spew)
			{
				outlet_list(x->x_outputList, 0, x->numFilters, x->growthList);
				outlet_float(x->x_growthOut, totalGrowth);
			}

			// update mask
			for(i=0; i<x->numFilters; i++)
			{
				if(x->analysisBuf[i] > x->mask[i])
				{
					x->mask[i] = x->analysisBuf[i];
					x->numPeriods[i] = 0;
				}
				else
					if(++x->numPeriods[i] >= x->maskPeriods)
						x->mask[i] *= x->maskDecay;
			}

			x->prevTotalGrowth = totalGrowth;
		}
	}

	post("analyzed %i frames", nFrames);
}
static void specFlatness_tilde_bang(t_specFlatness *x)
{
    int i, j, window, windowHalf, bangSample;
    t_sample *signal_R, *signal_I;
    t_float dividend, divisor, windowHalfPlusOneRecip, flatness, *windowFuncPtr;
	double currentTime,timef =0.0;
    
    window = x->window;
    windowHalf = window*0.5;
    windowHalfPlusOneRecip = 1.0/(t_float)(windowHalf+1);
	
	// create local memory
   	signal_R = (t_sample *)t_getbytes(window*sizeof(t_sample));
	signal_I = (t_sample *)t_getbytes((windowHalf+1)*sizeof(t_sample));
    
	//currentTime = clock_gettimesince(x->lastDspTime);
    clock_getftime(&timef);
    currentTime =  timef - x->lastDspTime;
    
	bangSample = (int)(((currentTime/1000.0)*x->sr)+0.5); // round
    
	if (bangSample < 0)
        bangSample = 0;
    else if ( bangSample >= x->n )
        bangSample = x->n - 1;
    
	// construct analysis window using bangSample as the end of the window
	for(i=0, j=bangSample; i<window; i++, j++)
		signal_R[i] = x->signal_R[j];
    
	// set window function
	windowFuncPtr = x->hann; //default case to get rid of compile warning
    
	switch(x->windowFunction)
	{
		case 0:
			break;
		case 1:
			windowFuncPtr = x->blackman;
			break;
		case 2:
			windowFuncPtr = x->cosine;
			break;
		case 3:
			windowFuncPtr = x->hamming;
			break;
		case 4:
			windowFuncPtr = x->hann;
			break;
		default:
			break;
	};
    
	// if windowFunction == 0, skip the windowing (rectangular)
	if(x->windowFunction>0)
		for(i=0; i<window; i++, windowFuncPtr++)
			signal_R[i] *= *windowFuncPtr;
    
	mayer_realfft(window, signal_R);
	tIDLib_realfftUnpack(window, windowHalf, signal_R, signal_I);
	tIDLib_power(windowHalf+1, signal_R, signal_I);
    
	if(!x->powerSpectrum)
		tIDLib_mag(windowHalf+1, signal_R);
    
	dividend=1; // to get the product of all terms for geometric mean
	divisor=0;
	flatness=0;
	
	// geometric mean
	// take the nth roots first so as not to lose data.
	for(i=0; i<=windowHalf; i++)
        x->nthRoots[i] = pow(signal_R[i], windowHalfPlusOneRecip);
    
	// take the product of nth roots
	// what to do with values that are zero?  for now, ignoring them.	
	for(i=0; i<=windowHalf; i++)
		if(x->nthRoots[i] != 0)
			dividend *= x->nthRoots[i];
    
	for(i=0; i<=windowHalf; i++)
		divisor += signal_R[i];
	
	divisor *= windowHalfPlusOneRecip; // arithmetic mean
	
	if(divisor==0)
		divisor = 1;
	
	flatness = dividend/divisor;
	
	outlet_float(x->x_flatness, flatness);
    
	// free local memory
	t_freebytes(signal_R, window*sizeof(t_sample));
	t_freebytes(signal_I, (windowHalf+1)*sizeof(t_sample));
}
Beispiel #11
0
static void specCentroid_analyze(t_specCentroid *x, t_floatarg start, t_floatarg n)
{
	int i, j, old_window, window, window_half, start_samp, end_samp, length_samp;
	float *window_func_ptr;
    float dividend, divisor, centroid;
	t_sample *signal_I;
	t_garray *a;

	if(!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
        pd_error(x, "%s: no such array", x->x_arrayname->s_name);
    else if(!garray_getfloatwords(a, &x->x_array_points, &x->x_vec))
    	pd_error(x, "%s: bad template for specCentroid", x->x_arrayname->s_name);
	else
	{

	start_samp = start;
	
	if(start_samp < 0)
		start_samp = 0;

	if(n)
		end_samp = start_samp + n-1;
	else
		end_samp = start_samp + x->window-1;
		
	if(end_samp > x->x_array_points)
		end_samp = x->x_array_points-1;

	length_samp = end_samp - start_samp + 1;

	if(end_samp <= start_samp)
	{
		error("bad range of samples.");
		return;
	}
		
	if(length_samp > x->powers_of_two[x->pow_two_arr_size-1])
	{
		post("WARNING: specCentroid: window truncated because requested size is larger than the current max_window setting. Use the max_window method to allow larger windows. Sizes of more than 131072 may produce unreliable results.");
		length_samp = x->powers_of_two[x->pow_two_arr_size-1];
		window = length_samp;
		end_samp = start_samp + window - 1;
	}
	else
	{
		i=0;
		while(length_samp > x->powers_of_two[i])
			i++;

		window = x->powers_of_two[i];
	}

	window_half = window * 0.5;

	if(x->window != window)
	{
		old_window = x->window;
		x->window = window;
		x->signal_R = (t_sample *)t_resizebytes(x->signal_R, old_window*sizeof(t_sample), window*sizeof(t_sample));
	}
	
	if(x->window_func_size != length_samp)
	{
		x->blackman = (float *)t_resizebytes(x->blackman, x->window_func_size*sizeof(float), length_samp*sizeof(float));
		x->cosine = (float *)t_resizebytes(x->cosine, x->window_func_size*sizeof(float), length_samp*sizeof(float));
		x->hamming = (float *)t_resizebytes(x->hamming, x->window_func_size*sizeof(float), length_samp*sizeof(float));
		x->hann = (float *)t_resizebytes(x->hann, x->window_func_size*sizeof(float), length_samp*sizeof(float));

		x->window_func_size = length_samp;
		
		specCentroid_blackman_window(x->blackman, x->window_func_size);
		specCentroid_cosine_window(x->cosine, x->window_func_size);
		specCentroid_hamming_window(x->hamming, x->window_func_size);
		specCentroid_hann_window(x->hann, x->window_func_size);
	}

	// create local memory
	signal_I = (t_sample *)getbytes(window_half*sizeof(t_sample));

	// construct analysis window
	for(i=0, j=start_samp; j<=end_samp; i++, j++)
		x->signal_R[i] = x->x_vec[j].w_float;

	// set window
	window_func_ptr = x->hann; //default case to get rid of compile warning
	switch(x->window_function)
	{
		case 0:
			window_func_ptr = x->blackman;
			break;
		case 1:
			window_func_ptr = x->cosine;
			break;
		case 2:
			window_func_ptr = x->hamming;
			break;
		case 3:
			window_func_ptr = x->hann;
			break;
		default:
			break;
	};
	
	// then multiply against the chosen window
	for(i=0; i<length_samp; i++, window_func_ptr++)
		x->signal_R[i] *= *window_func_ptr;

	// then zero pad the end
	for(; i<window; i++)
		x->signal_R[i] = 0.0;

	mayer_realfft(window, x->signal_R);
	specCentroid_realfft_unpack(window, window_half, x->signal_R, signal_I);
	specCentroid_power(window_half, x->signal_R, signal_I);

	if(!x->power_spectrum)
		specCentroid_mag(window_half, x->signal_R);

	dividend=0;
	divisor=0;
	centroid=0;
	
	for(i=0; i<window_half; i++)
		dividend += x->signal_R[i]*(i*(x->sr/window));  // weight by bin freq

	for(i=0; i<window_half; i++)
		divisor += x->signal_R[i];
		
	if(divisor==0) divisor = 1; // don't divide by zero
	
	centroid = dividend/divisor;
		
	outlet_float(x->x_centroid, centroid);

	// free local memory
	t_freebytes(signal_I, window_half*sizeof(t_sample));

	}
}
Beispiel #12
0
static void specSkewness_tilde_bang(t_specSkewness_tilde *x)
{
    int i, j, window, windowHalf, bangSample;
    t_sample *signal_R, *signal_I;
    t_float dividend, centroid, std, divisor, skewness, *windowFuncPtr;
	double currentTime;

    window = x->window;
    windowHalf = window*0.5;

	// create local memory
   	signal_R = (t_sample *)t_getbytes(window*sizeof(t_sample));
	signal_I = (t_sample *)t_getbytes((windowHalf+1)*sizeof(t_sample));

	currentTime = clock_gettimesince(x->lastDspTime);
	bangSample = (int)(((currentTime/1000.0)*x->sr)+0.5); // round

	if (bangSample < 0)
        bangSample = 0;
    else if ( bangSample >= x->n )
        bangSample = x->n - 1;

	// construct analysis window using bangSample as the end of the window
	for(i=0, j=bangSample; i<window; i++, j++)
		signal_R[i] = x->signal_R[j];

	// set window function
	windowFuncPtr = x->hann; //default case to get rid of compile warning

	switch(x->windowFunction)
	{
		case 0:
			break;
		case 1:
			windowFuncPtr = x->blackman;
			break;
		case 2:
			windowFuncPtr = x->cosine;
			break;
		case 3:
			windowFuncPtr = x->hamming;
			break;
		case 4:
			windowFuncPtr = x->hann;
			break;
		default:
			break;
	};

	// if windowFunction == 0, skip the windowing (rectangular)
	if(x->windowFunction>0)
		for(i=0; i<window; i++, windowFuncPtr++)
			signal_R[i] *= *windowFuncPtr;

	mayer_realfft(window, signal_R);
	tIDLib_realfftUnpack(window, windowHalf, signal_R, signal_I);
	tIDLib_power(windowHalf+1, signal_R, signal_I);

	if(!x->powerSpectrum)
		tIDLib_mag(windowHalf+1, signal_R);

	dividend=0;
	divisor=0;
	centroid=0;

	for(i=0; i<=windowHalf; i++)
	{
		dividend += signal_R[i] * x->binFreqs[i];  // weight by bin freq
		divisor += signal_R[i];
	}

	divisor = (divisor==0)?1.0:divisor; // don't divide by zero

	centroid = dividend/divisor;

	dividend=0;
	std=0;

	for(i=0; i<=windowHalf; i++)
		dividend += pow((x->binFreqs[i] - centroid), 2) * signal_R[i];

	std = sqrt(dividend/divisor);
	std = pow(std, 3);
	std = (std==0)?1.0:std; // don't divide by zero

	dividend=0;
	skewness=0;

	for(i=0; i<=windowHalf; i++)
		dividend += pow((x->binFreqs[i] - centroid), 3) * signal_R[i];

	skewness = (dividend/divisor)/std;

	outlet_float(x->x_skewness, skewness);

	// free local memory
	t_freebytes(signal_R, window*sizeof(t_sample));
	t_freebytes(signal_I, (windowHalf+1)*sizeof(t_sample));
}
Beispiel #13
0
static void bfcc_tilde_bang(t_bfcc_tilde *x)
{
	int i, j, window, window_half, bang_sample;
	t_atom *listOut;
	t_sample *signal_R, *signal_I;
	double current_time;

	window = x->window;
	window_half = window * 0.5;
	
	// create local memory
	listOut = (t_atom *)getbytes(0);
	signal_R = (t_sample *)getbytes(0);
	signal_I = (t_sample *)getbytes(0);
	listOut = (t_atom *)t_resizebytes(listOut, 0, x->num_filters * sizeof(t_atom));
	signal_R = (t_sample *)t_resizebytes(signal_R, 0, window*sizeof(t_sample));
	signal_I = (t_sample *)t_resizebytes(signal_I, 0, window_half*sizeof(t_sample));
	
	current_time = clock_gettimesince(x->last_dsp_time);
	bang_sample = (int)(((current_time/1000.0)*x->sr)+0.5); // round

	if (bang_sample < 0)
        bang_sample = 0;
    else if ( bang_sample >= x->n )
        bang_sample = x->n - 1;
            
	// construct analysis window using bang_sample as the end of the window
	for(i=0, j=bang_sample; i<window; i++, j++)
		signal_R[i] = x->signal_R[j];
	
	switch(x->window_function)
	{
		case 0:
			bfcc_tilde_DSP_window(window, signal_R, x->blackman);
			break;
		case 1:
			bfcc_tilde_DSP_window(window, signal_R, x->cosine);
			break;
		case 2:
			bfcc_tilde_DSP_window(window, signal_R, x->hamming);
			break;
		case 3:
			bfcc_tilde_DSP_window(window, signal_R, x->hann);
			break;
		default:
			break;
	};
	
	mayer_realfft(window, signal_R);
	bfcc_tilde_realfft_unpack(window, window_half, signal_R, signal_I);
	bfcc_tilde_abs(window_half, signal_R, signal_I);

// power spectrum sometimes generates lower scores than magnitude. make it optional.
	if(x->power_spectrum)
		bfcc_tilde_square(window_half, signal_R);

	bfcc_tilde_filterbank_multiply(signal_R, x->normalize, x->x_filterbank, x->x_indices, x->num_filters);
	bfcc_tilde_compute_bfccs(x->bfcc, signal_R, x->num_filters);
		
	for(i=0; i<x->num_filters; i++)
		SETFLOAT(listOut+i, x->bfcc[i]);

	outlet_list(x->x_featureList, 0, x->num_filters, listOut);

	// free local memory
	t_freebytes(listOut, x->num_filters * sizeof(t_atom));
	t_freebytes(signal_R, window * sizeof(t_sample));
	t_freebytes(signal_I, window_half * sizeof(t_sample));
}
Beispiel #14
0
static void specRolloff_tilde_bang(t_specRolloff_tilde *x)
{
    int i, j, window, windowHalf, bangSample;
    t_sample *signal_R, *signal_I;
    t_float energy, energyTarget, rolloff, *windowFuncPtr;
	double currentTime;

    window = x->window;
    windowHalf = window*0.5;

	// create local memory
   	signal_R = (t_sample *)t_getbytes(window*sizeof(t_sample));
	signal_I = (t_sample *)t_getbytes((windowHalf+1)*sizeof(t_sample));

	currentTime = clock_gettimesince(x->lastDspTime);
	bangSample = (int)(((currentTime/1000.0)*x->sr)+0.5); // round

	if (bangSample < 0)
        bangSample = 0;
    else if ( bangSample >= x->n )
        bangSample = x->n - 1;

	// construct analysis window using bangSample as the end of the window
	for(i=0, j=bangSample; i<window; i++, j++)
		signal_R[i] = x->signal_R[j];

	// set window function
	windowFuncPtr = x->hann; //default case to get rid of compile warning

	switch(x->windowFunction)
	{
		case 0:
			break;
		case 1:
			windowFuncPtr = x->blackman;
			break;
		case 2:
			windowFuncPtr = x->cosine;
			break;
		case 3:
			windowFuncPtr = x->hamming;
			break;
		case 4:
			windowFuncPtr = x->hann;
			break;
		default:
			break;
	};

	// if windowFunction == 0, skip the windowing (rectangular)
	if(x->windowFunction>0)
		for(i=0; i<window; i++, windowFuncPtr++)
			signal_R[i] *= *windowFuncPtr;

	mayer_realfft(window, signal_R);
	tIDLib_realfftUnpack(window, windowHalf, signal_R, signal_I);
	tIDLib_power(windowHalf+1, signal_R, signal_I);

	if(!x->powerSpectrum)
		tIDLib_mag(windowHalf+1, signal_R);

	energyTarget=0;

	for(i=0; i<=windowHalf; i++)
		energyTarget += signal_R[i];

	energyTarget *= x->concentration;

	energy=0;
	i=0;

	while(energy <= energyTarget)
	{
		energy += signal_R[i];
		i++;

		if(i>windowHalf)
			break;
	}

	i = (i==0)?1:i;

	rolloff = x->binFreqs[i-1]; // back up one because the last one went over...

	outlet_float(x->x_rolloff, rolloff);

	// free local memory
	t_freebytes(signal_R, window*sizeof(t_sample));
	t_freebytes(signal_I, (windowHalf+1)*sizeof(t_sample));
}
Beispiel #15
0
static void mTXRfftMatrix (MTXRfft *x, t_symbol *s, 
			      int argc, t_atom *argv)
{
  int rows = atom_getint (argv++);
  int columns = atom_getint (argv++);
  int columns_re = (columns>>1)+1; /* N/2+1 samples needed for real part of realfft */
  int size = rows * columns;
  int in_size = argc-2;
  int size2 = columns_re * rows + 2; /* +2 since the list also contains matrix row+col */
  int fft_count;
  t_atom *list_re = x->list_re;
  t_atom *list_im = x->list_im;
#ifdef HAVE_FFTW3_H
  fftw_complex *f_out = x->f_out;
  double *f_in = x->f_in;
#else
  t_float *f_re = x->f_re;
  t_float *f_im = x->f_im;
#endif

  /* fftsize check */
  if (!size)
    post("mtx_rfft: invalid dimensions");
  else if (in_size<size)
    post("mtx_rfft: sparse matrix not yet supported: use \"mtx_check\"");
  else if (columns < 4){
    post("mtx_rfft: matrix must have at least 4 columns");
  }
  else if (columns == (1 << ilog2(columns))) {
    /* ok, do the FFT! */

    /* memory things */
#ifdef HAVE_FFTW3_H
    if ((x->rows!=rows)||(columns!=x->fftn)){
       f_out=(fftw_complex*)realloc(f_out, sizeof(fftw_complex)*(size2-2));
       f_in=(double*)realloc(f_in, sizeof(double)*size);
       x->f_in = f_in;
       x->f_out = f_out;
       for (fft_count=0; fft_count<x->rows; fft_count++) {
          fftw_destroy_plan(x->fftplan[fft_count]);
       }
       x->fftplan = (fftw_plan*)realloc(x->fftplan, sizeof(fftw_plan)*rows);
       for (fft_count=0; fft_count<rows; fft_count++, f_in+=columns, f_out+=columns_re) {
	  x->fftplan[fft_count] = fftw_plan_dft_r2c_1d (columns,f_in,f_out,FFTW_ESTIMATE);
       }
       x->fftn=columns;
       x->rows=rows;
       f_in=x->f_in;
       f_out=x->f_out;
    }
#else
    f_re=(t_float*)realloc(f_re, sizeof(t_float)*size);
    f_im=(t_float*)realloc(f_im, sizeof(t_float)*size);
    x->f_re = f_re;
    x->f_im = f_im;
#endif
    list_re=(t_atom*)realloc(list_re, sizeof(t_atom)*size2);
    list_im=(t_atom*)realloc(list_im, sizeof(t_atom)*size2);

    x->size = size;
    x->size2 = size2;
    x->list_im = list_im;
    x->list_re = list_re;

    /* main part */
#ifdef HAVE_FFTW3_H
    readDoubleFromList (size, argv, f_in);
#else
    readFloatFromList (size, argv, f_re);
#endif

    list_re += 2;
    list_im += 2;
    for (fft_count=0;fft_count<rows;fft_count++){ 
#ifdef HAVE_FFTW3_H
      fftw_execute(x->fftplan[fft_count]);
      writeFFTWComplexPartIntoList(columns_re,list_re,f_out,REALPART);
      writeFFTWComplexPartIntoList(columns_re,list_im,f_out,IMAGPART);
      f_out+=columns_re;
#else
      mayer_realfft (columns, f_re);
      fftRestoreImag (columns, f_re, f_im);
      writeFloatIntoList (columns_re, list_re, f_re);
      writeFloatIntoList (columns_re, list_im, f_im);
      f_im += columns;
      f_re += columns;
#endif
      list_re += columns_re;
      list_im += columns_re;
    }

    list_re = x->list_re;
    list_im = x->list_im;
      
    SETSYMBOL(list_re, gensym("matrix"));
    SETSYMBOL(list_im, gensym("matrix"));
    SETFLOAT(list_re, rows);
    SETFLOAT(list_im, rows);
    SETFLOAT(list_re+1, columns_re);
    SETFLOAT(list_im+1, columns_re);
    outlet_anything(x->list_im_out, gensym("matrix"), 
		    x->size2, list_im);
    outlet_anything(x->list_re_out, gensym("matrix"), 
		    x->size2, list_re);
  }
  else
    post("mtx_rowfft: rowvector size no power of 2!");

}
Beispiel #16
0
static void specCentroid_analyze(t_specCentroid *x, t_floatarg start, t_floatarg n)
{
	int i, j, oldWindow, window, windowHalf, startSamp, endSamp, lengthSamp;
    t_float dividend, divisor, centroid, *windowFuncPtr;
	t_sample *signal_I;
	t_garray *a;

	if(!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
        pd_error(x, "%s: no such array", x->x_arrayname->s_name);
    else if(!garray_getfloatwords(a, &x->x_arrayPoints, &x->x_vec))
    	pd_error(x, "%s: bad template for specCentroid", x->x_arrayname->s_name);
	else
	{

	startSamp = start;
	startSamp = (startSamp<0)?0:startSamp;

	if(n)
		endSamp = startSamp + n-1;
	else
		endSamp = startSamp + x->window-1;

	if(endSamp > x->x_arrayPoints)
		endSamp = x->x_arrayPoints-1;

	lengthSamp = endSamp-startSamp+1;

	if(endSamp <= startSamp)
	{
		error("bad range of samples.");
		return;
	}

	if(lengthSamp > x->powersOfTwo[x->powTwoArrSize-1])
	{
		post("WARNING: specCentroid: window truncated because requested size is larger than the current max_window setting. Use the max_window method to allow larger windows.");
		lengthSamp = x->powersOfTwo[x->powTwoArrSize-1];
		window = lengthSamp;
		endSamp = startSamp + window - 1;
	}
	else
	{
		i=0;
		while(lengthSamp > x->powersOfTwo[i])
			i++;

		window = x->powersOfTwo[i];
	}

	windowHalf = window * 0.5;

	if(x->window != window)
	{
		oldWindow = x->window;
		x->window = window;

		x->signal_R = (t_sample *)t_resizebytes(x->signal_R, oldWindow*sizeof(t_sample), x->window*sizeof(t_sample));
	}

	if(x->windowFuncSize != lengthSamp)
	{
		x->blackman = (t_float *)t_resizebytes(x->blackman, x->windowFuncSize*sizeof(t_float), lengthSamp*sizeof(t_float));
		x->cosine = (t_float *)t_resizebytes(x->cosine, x->windowFuncSize*sizeof(t_float), lengthSamp*sizeof(t_float));
		x->hamming = (t_float *)t_resizebytes(x->hamming, x->windowFuncSize*sizeof(t_float), lengthSamp*sizeof(t_float));
		x->hann = (t_float *)t_resizebytes(x->hann, x->windowFuncSize*sizeof(t_float), lengthSamp*sizeof(t_float));

		x->windowFuncSize = lengthSamp;

		tIDLib_blackmanWindow(x->blackman, x->windowFuncSize);
		tIDLib_cosineWindow(x->cosine, x->windowFuncSize);
		tIDLib_hammingWindow(x->hamming, x->windowFuncSize);
		tIDLib_hannWindow(x->hann, x->windowFuncSize);
	}

	// create local memory
	signal_I = (t_sample *)t_getbytes((windowHalf+1)*sizeof(t_sample));

	// construct analysis window
	for(i=0, j=startSamp; j<=endSamp; i++, j++)
		x->signal_R[i] = x->x_vec[j].w_float;

	// set window function
	windowFuncPtr = x->hann; //default case to get rid of compile warning

	switch(x->windowFunction)
	{
		case 0:
			break;
		case 1:
			windowFuncPtr = x->blackman;
			break;
		case 2:
			windowFuncPtr = x->cosine;
			break;
		case 3:
			windowFuncPtr = x->hamming;
			break;
		case 4:
			windowFuncPtr = x->hann;
			break;
		default:
			break;
	};

	// if windowFunction == 0, skip the windowing (rectangular)
	if(x->windowFunction>0)
		for(i=0; i<lengthSamp; i++, windowFuncPtr++)
			x->signal_R[i] *= *windowFuncPtr;

	// then zero pad the end
	for(; i<window; i++)
		x->signal_R[i] = 0.0;

	mayer_realfft(window, x->signal_R);
	tIDLib_realfftUnpack(window, windowHalf, x->signal_R, signal_I);
	tIDLib_power(windowHalf+1, x->signal_R, signal_I);

	// power spectrum sometimes generates lower scores than magnitude. make it optional.
	if(!x->powerSpectrum)
		tIDLib_mag(windowHalf+1, x->signal_R);

	dividend=0;
	divisor=0;
	centroid=0;
	
	for(i=0; i<=windowHalf; i++)
		dividend += x->signal_R[i]*(i*(x->sr/window));  // weight by bin freq

	for(i=0; i<=windowHalf; i++)
		divisor += x->signal_R[i];
		
	if(divisor==0) divisor = 1; // don't divide by zero
	
	centroid = dividend/divisor;
		
	outlet_float(x->x_centroid, centroid);

	// free local memory
	t_freebytes(signal_I, (windowHalf+1)*sizeof(t_sample));
	}
}
Beispiel #17
0
/*************process replacing************/
t_int *phasevoc_tilde_perform (t_int *w)
{
  t_phasevoc_tilde *x = (t_phasevoc_tilde *)(w[1]);
  t_sample  *in = (t_sample *)(w[2]);
  t_sample *out1 = (t_sample *)(w[3]);
  int n = (int)(w[4]);
  t_float n2 = (t_float)n;
  x->n = n;
  int i, j;
  t_float psfact = phasevoc_tilde_cents(x);
  t_float tsfact = x->timestretch;
  t_float buffpos;
  long maskFFT=x->fftSize-1;
 

  //unless samphold or pause is on, always fill the circBuff
  if(x->pause!=1)
    {
      for(i=0; i<n; i++)
	{
	  x->circBuff[x->circBuffIndex++] = in[i];
	  while(x->circBuffIndex > (x->circBuffLength-1))x->circBuffIndex-=(x->circBuffLength);
	  while(x->circBuffIndex < 0 )x->circBuffIndex += x->circBuffLength;
	  
	}
      x->delayCount+=n;
    }

 
 if(x->delayCount>x->fftSize)
    {
      if(!x->sampHoldBuffLength)
	{
	  //init the indeces for this read-out fromt the circ buff
	  x->circBuffWindowBackIndex = x->circBuffWindowStart;
	  x->circBuffWindowFrontIndex = x->circBuffWindowBackIndex + (x->hopSize*psfact);
	}

      else
	{
	  //init the indeces for this read-out fromt the sampholdbuff
	  x->sampHoldBuffWindowBackIndex = x->sampHoldBuffWindowStart;
	  x->sampHoldBuffWindowFrontIndex = x->sampHoldBuffWindowBackIndex + (x->hopSize*psfact);
	}


      //check for dsp_tick
      if(x->dsp_tick == (x->buffer_limit*x->overlap))
	x->dsp_tick = 0;
      
      
      if((x->dsp_tick%x->buffer_limit)==0)
	{
	  //buffer in the samples if no sampbuff
	  if(!x->sampHoldBuffLength)
	    {
	      for(i=0; i<x->fftSize; i++)
		{
		  x->inFrontBuff[i] =  phasevoc_tilde_interpolate(x->circBuff, x->circBuffLength, x->circBuffWindowFrontIndex);
		  x->inBackBuff[i] =  phasevoc_tilde_interpolate(x->circBuff, x->circBuffLength, x->circBuffWindowBackIndex);
		  
		  //increment the indices by the pitchshifting factor
		  x->circBuffWindowFrontIndex+=psfact;
		  x->circBuffWindowBackIndex+=psfact;
		  
		  //wrap 'em
		  while(x->circBuffWindowFrontIndex>(x->circBuffLength-1))
		      x->circBuffWindowFrontIndex-=(x->circBuffLength);
	
		  while(x->circBuffWindowFrontIndex<0)
		      x->circBuffWindowFrontIndex+=x->circBuffLength;
		  while(x->circBuffWindowBackIndex>(x->circBuffLength-1))x->circBuffWindowBackIndex-=(x->circBuffLength);
		  while(x->circBuffWindowBackIndex<0)x->circBuffWindowBackIndex+=x->circBuffLength;
		}
	    }
	  //buffer in the samples if sampbuff
	  else
	    {
	      for(i=0; i<x->fftSize; i++)
		{
		  x->inFrontBuff[i] =  phasevoc_tilde_interpolate(x->sampHoldBuff, x->sampHoldBuffLength, x->sampHoldBuffWindowFrontIndex);
		  x->inBackBuff[i] =  phasevoc_tilde_interpolate(x->sampHoldBuff, x->sampHoldBuffLength, x->sampHoldBuffWindowBackIndex);
		  
		  //increment the indices by the pitchshifting factor
		  x->sampHoldBuffWindowFrontIndex+=psfact;
		  x->sampHoldBuffWindowBackIndex+=psfact;
		  
		  //wrap 'em
		  while(x->sampHoldBuffWindowFrontIndex>(x->sampHoldBuffLength-1))
		      x->sampHoldBuffWindowFrontIndex-=(x->sampHoldBuffLength);
		   
		  while(x->sampHoldBuffWindowFrontIndex<0)
		      x->sampHoldBuffWindowFrontIndex+=x->sampHoldBuffLength;
		    
		  while(x->sampHoldBuffWindowBackIndex>(x->sampHoldBuffLength-1))x->sampHoldBuffWindowBackIndex-=(x->sampHoldBuffLength);
		  while(x->sampHoldBuffWindowBackIndex<0)x->sampHoldBuffWindowBackIndex+=x->sampHoldBuffLength;
		}
	    }

	  //window the signal
	  for(i=0; i<x->fftSize; i++)
	    {

	      x->inFrontBuff[i] *= x->analWindow[i];
	      x->inBackBuff[i] *= x->analWindow[i];

	    }
	  
	  
	  
	  //go to frequency domain
	  mayer_realfft(x->fftSize, x->inFrontBuff);
	  mayer_realfft(x->fftSize, x->inBackBuff);

	  
	  
	  //unpack the bizzarely packed mayer ffts
	  for(i=0; i<=x->fftHalfSize; i++)// halfSizeFFT = nyquist
	    {
	      x->frontReal[i] = x->inFrontBuff[i];
	      x->backReal[i] = x->inBackBuff[i];

	    }
	  x->frontImag[0] = x->backImag[0]= 0;  // 0 DC
	  
	  for(i=(x->fftSize-1), j=1; i>x->fftHalfSize; i--, j++)
	    {

	      x->frontImag[j] = x->inFrontBuff[i];
	      x->backImag[j] = x->inBackBuff[i];


	    }
	  
	  x->frontImag[x->fftHalfSize]=x->backImag[x->fftHalfSize]=0; //halfSizeFFT empty
	  
	  for(i = 0; i <= x->fftHalfSize; i++)
	    {
	      //first normalize over magnitude so we get phase only
	      x->rsqrt[i] = q8_rsqrt((x->prevReal[i] * x->prevReal[i]) +
				     (x->prevImag[i] * x->prevImag[i]) +
				     .000000000000000000001f);
	      x->prevReal[i] *= x->rsqrt[i];
	      x->prevImag[i] *= x->rsqrt[i];

	      x->conjReal[i] = (x->prevReal[i] * x->backReal[i]) + (x->prevImag[i] * x->backImag[i]) +
	      	.0000000000000001;
	      x->conjImag[i] = (x->prevImag[i] * x->backReal[i]) - (x->prevReal[i] * x->backImag[i]);

	    	      
	      x->rsqrt[i] = q8_rsqrt((x->conjReal[i] * x->conjReal[i]) +
	      			     (x->conjImag[i] * x->conjImag[i]));
	      x->conjReal[i] *= x->rsqrt[i];
	      x->conjImag[i] *= x->rsqrt[i];

	      //then add the front window (complex multiply) this time keeping magnitudes, and store the info for the next time around
	      x->outReal[i] = (x->conjReal[i] * x->frontReal[i]) - (x->conjImag[i] * x->frontImag[i]);
	      
	      x->outImag[i] = (x->conjReal[i] * x->frontImag[i]) + (x->conjImag[i] * x->frontReal[i]);
	      x->prevImag[i] = x->outImag[i];
	      x->prevReal[i] = x->outReal[i];
	    }

	  //phase has been propogated, repack for ifft
	  for(i=0; i<=x->fftHalfSize; i++)  // +1 to include Nyquist
	    x->outSpectra[i] = x->outReal[i];
	  
	  for(j = x->fftHalfSize -1, i = x->fftHalfSize + 1; i < x->fftSize; j--, i++)
	    x->outSpectra[i] = x->outImag[j];
	  
	  //back to time domain
	  mayer_realifft(x->fftSize, x->outSpectra);

	  //william brent's overlap/add function:
	  //window the synthesis
	  for(i=0; i<x->fftSize; i++)
	    x->outSpectra[i] *= x->synthWindow[i];//synthWindow is 2/3/fftSize*analWindow
	  
	  //  first shift output in nonoverlapped buffer
	  for(i=0; i<((x->overlap-1)*x->fftSize); i++)
	    x->nonoverlappedOutBuff[i] = x->nonoverlappedOutBuff[x->fftSize+i];
	 
	  //  then, write a new window in
	  for(i=0; i<x->fftSize; i++)
	    x->nonoverlappedOutBuff[((x->overlap-1)*x->fftSize)+i] = x->outSpectra[i];
	  
	  // init this chunk of the final output so it can be summed in the for() below
	  for(i=0; i<(x->hopSize); i++)
	    x->outBuff[i] = 0.0;
	  
	  // do the overlap/add: add the last hopsize of the first
	  for(i=0; i<x->overlap; i++)
	    for(j=0; j<(x->hopSize); j++)
	      x->outBuff[j] += x->nonoverlappedOutBuff[(i*x->fftSize)+((x->overlap-i-1)*x->hopSize)+j/*overlap_chunk*/];
	  x->fft_tick=0;
	}
      
      //output
      for(i=0; i<n; i++, out1++)
	*out1 = x->outBuff[(x->fft_tick*n)+i];
      if(!x->sampHoldBuffLength)
	buffpos = 1.0-(x->circBuffIndex - x->circBuffWindowStart) / x->circBuffLength;
      else
	buffpos = 1.0-(x->sampHoldBuffIndex - x->sampHoldBuffWindowStart) / x->sampHoldBuffLength;
      while(buffpos>=1.0)buffpos -= 1.0;
      while(buffpos<=0.0)buffpos += 1.0;
      outlet_float(x->buffPos, buffpos);
      x->fft_tick++;
      x->dsp_tick++;

      //increment the read start point and wrap it
      if(!x->sampHoldBuffLength)
	{
	  x->circBuffWindowStart+=n*tsfact;
	  while(x->circBuffWindowStart > (x->circBuffLength-1))x->circBuffWindowStart-=x->circBuffLength;
	  while(x->circBuffWindowStart<0)x->circBuffWindowStart+=x->circBuffLength;
	}

      else
	{
	  x->sampHoldBuffWindowStart+=n*tsfact;
	  while(x->sampHoldBuffWindowStart > (x->sampHoldBuffLength-1))x->sampHoldBuffWindowStart-=x->sampHoldBuffLength;
	  while(x->sampHoldBuffWindowStart<0)x->sampHoldBuffWindowStart+=x->sampHoldBuffLength;
	}

      return(w+5);
    }
 else
   {
     *out1++ = 0.0;
     return(w+5);

   }
   
}
static void barkSpec_tilde_bang(t_barkSpec *x)
{
    int i, j, window, windowHalf, bangSample;
	t_atom *listOut;
	t_sample *signal_R, *signal_I;
	t_float *windowFuncPtr;
	double currentTime, timef = 0.0;
    
	window = x->window;
	windowHalf = window*0.5;
    
	// create local memory
	listOut = (t_atom *)t_getbytes_(x->numFilters*sizeof(t_atom));
	signal_R = (t_sample *)t_getbytes_(window*sizeof(t_sample));
	signal_I = (t_sample *)t_getbytes_((windowHalf+1)*sizeof(t_sample));
    
	//currentTime = clock_gettimesince(x->lastDspTime);
    clock_getftime(&timef);
    currentTime =  timef - x->lastDspTime;
    
	bangSample = (int)(((currentTime/1000.0)*x->sr)+0.5); // round
    
	if (bangSample < 0)
		bangSample = 0;
	else if ( bangSample >= x->n )
		bangSample = x->n - 1;
    
	// construct analysis window using bangSample as the end of the window
	for(i=0, j=bangSample; i<window; i++, j++)
		signal_R[i] = x->signal_R[j];
    
	// set window function
	windowFuncPtr = x->hann; //default case to get rid of compile warning
    
	switch(x->windowFunction)
	{
		case 0:
			break;
		case 1:
			windowFuncPtr = x->blackman;
			break;
		case 2:
			windowFuncPtr = x->cosine;
			break;
		case 3:
			windowFuncPtr = x->hamming;
			break;
		case 4:
			windowFuncPtr = x->hann;
			break;
		default:
			break;
	};
    
	// if windowFunction == 0, skip the windowing (rectangular)
	if(x->windowFunction>0)
		for(i=0; i<window; i++, windowFuncPtr++)
			signal_R[i] *= *windowFuncPtr;
    
	mayer_realfft(window, signal_R);
	tIDLib_realfftUnpack(window, windowHalf, signal_R, signal_I);
	tIDLib_power(windowHalf+1, signal_R, signal_I);
    
	// power spectrum sometimes generates lower scores than magnitude. make it optional.
	if(!x->powerSpectrum)
		tIDLib_mag(windowHalf+1, signal_R);
    
	tIDLib_filterbankMultiply(signal_R, x->normalize, x->filterAvg, x->x_filterbank, x->numFilters);
    
	for(i=0; i<x->numFilters; i++)
		SETFLOAT(listOut+i, signal_R[i]);
    
	outlet_list(x->x_featureList, 0, x->numFilters, listOut);
    
	// free local memory
	t_freebytes_(listOut, x->numFilters*sizeof(t_atom));
	t_freebytes_(signal_R, window*sizeof(t_sample));
	t_freebytes_(signal_I, (windowHalf+1)*sizeof(t_sample));    
    
}
Beispiel #19
0
static void magSpec_tilde_bang(t_magSpec_tilde *x)
{
    int i, j, window, windowHalf, bangSample;
    t_atom *listOut;
    t_sample *signal_R, *signal_I;
    t_float *windowFuncPtr;
	double currentTime;

    window = x->window;
    windowHalf = window*0.5;
	
	// create local memory
	listOut = (t_atom *)t_getbytes((windowHalf+1)*sizeof(t_atom));
   	signal_R = (t_sample *)t_getbytes(window*sizeof(t_sample));
	signal_I = (t_sample *)t_getbytes((windowHalf+1)*sizeof(t_sample));
	
	currentTime = clock_gettimesince(x->lastDspTime);
	bangSample = (int)(((currentTime/1000.0)*x->sr)+0.5); // round

	if (bangSample < 0)
        bangSample = 0;
    else if ( bangSample >= x->n )
        bangSample = x->n - 1;
            
	// construct analysis window using bangSample as the end of the window
	for(i=0, j=bangSample; i<window; i++, j++)
		signal_R[i] = x->signal_R[j];

	// set window function
	windowFuncPtr = x->hann; //default case to get rid of compile warning

	switch(x->windowFunction)
	{
		case 0:
			break;
		case 1:
			windowFuncPtr = x->blackman;
			break;
		case 2:
			windowFuncPtr = x->cosine;
			break;
		case 3:
			windowFuncPtr = x->hamming;
			break;
		case 4:
			windowFuncPtr = x->hann;
			break;
		default:
			break;
	};

	// if windowFunction == 0, skip the windowing (rectangular)
	if(x->windowFunction>0)
		for(i=0; i<window; i++, windowFuncPtr++)
			signal_R[i] *= *windowFuncPtr;

	mayer_realfft(window, signal_R);
	tIDLib_realfftUnpack(window, windowHalf, signal_R, signal_I);
	tIDLib_power(windowHalf+1, signal_R, signal_I);

	if(!x->powerSpectrum)
		tIDLib_mag(windowHalf+1, signal_R);
		
	if(x->normalize)
		tIDLib_normal(windowHalf+1, signal_R);
		
	for(i=0; i<=windowHalf; i++)
		SETFLOAT(listOut+i, signal_R[i]);

 	outlet_list(x->x_mag, 0, windowHalf+1, listOut);

	// free local memory
	t_freebytes(listOut, (windowHalf+1)*sizeof(t_atom));
	t_freebytes(signal_R, window*sizeof(t_sample));
	t_freebytes(signal_I, (windowHalf+1)*sizeof(t_sample));
}