Esempio n. 1
0
void update_pwelch(double *buffer)
{
	unsigned int ctr = 0;
	// Hanning window the new segment
	window(buffer);

	// Do the FFT, we get square magnitudes in return
	do_fft(buffer);

	// If this is the first segment, just update the global estimate
	if (estimates == 0) {
		for (ctr = 0; ctr < N; ctr++) {
			global_estimate[ctr] += buffer[ctr];	
		}
		estimates++;
	}
	else
	{
		for (ctr = 0; ctr < N; ctr++) {
			// Unroll the last time average, generate a new time average per bin
			global_estimate[ctr] = global_estimate[ctr]*estimates + buffer[ctr];
			global_estimate[ctr] /= (float)(estimates+1);
		}
		estimates++;
	}
}
Esempio n. 2
0
// want compiler to be able to make the tail recursion optimisation
static int real_add_audio(struct simple_soft_ctx *ctx, const float *in, size_t n, int buf_count)
{
	int bufp = ctx->audio_bufp;
	const int nr_samp = ctx->nr_samp;

	size_t remain = 0;
	size_t cpy = MIN(n, nr_samp/2-bufp);
	if(ctx->channels == 1) {
		memcpy(ctx->cur_buf+bufp, in, sizeof(float)*cpy);
		in += cpy;
	} else {
		float *p = ctx->cur_buf+bufp;
		for(unsigned int i=0; i<cpy; i++, p++, in += 2) *p = (in[0]+in[1])/2;
	}
	remain = n - cpy;
	bufp = (bufp + cpy)%(nr_samp/2);

	//ctx->sample_count += cpy;
	ctx->audio_bufp = bufp;

	if(bufp == 0) { // do we have enough samples to do beat detection?
		float *fft = do_fft(ctx, ctx->cur_buf, ctx->prev_buf);
		beat_ctx_update(ctx->beat, fft, nr_samp/2);

		float *tmp = ctx->cur_buf;
		ctx->cur_buf = ctx->prev_buf;
		ctx->prev_buf = tmp;

		buf_count++;
	}

	if(remain > 0) return real_add_audio(ctx, in, remain, buf_count);
	return buf_count;
}
Esempio n. 3
0
void do_reverse_fft(vector<Data>& b) {
    do_fft(b);
    int n = b.size();
    reverse(b.begin() + 1, b.end());
    for (int i = 0; i < n; i++)
        b[i] /= n;
}
Esempio n. 4
0
/*! \brief Get FFT data.
 *  \param fftPoints Buffer to copy FFT data
 *  \param fftSize Current FFT size (output).
 */
void rx_fft_c::get_fft_data(std::complex<float>* fftPoints, unsigned int &fftSize)
{
    boost::mutex::scoped_lock lock(d_mutex);
    if(d_fftmode >= 1) {
        if(averagecount > 0) {
            float normalize = 1.0 / averagecount;
            //printf("%d ", averagecount);
            for(unsigned int s=0; s<d_fftsize; s++) {
                fftPoints[s] = sqrt(normalize * averager[s]);
                averager[s] = 0;
            }
            averagecount = 0;
            fftSize = d_fftsize;
        } else {
            fftSize = 0;
        }
    } else {
        if (d_cbuf.size() < d_fftsize)
        {
            // not enough samples in the buffer
            fftSize = 0;

            return;
        }

        /* perform FFT */
        do_fft(d_cbuf.linearize(), d_cbuf.size());  // FIXME: array_one() and two() may be faster
        //d_cbuf.clear();

        /* get FFT data */
        memcpy(fftPoints, d_fft->get_outbuf(), sizeof(gr_complex)*d_fftsize);
        fftSize = d_fftsize;
    }
}
Esempio n. 5
0
/*! \brief Receiver FFT work method.
 *  \param noutput_items
 *  \param input_items
 *  \param output_items
 *
 * This method does nothing except throwing the incoming samples into the
 * circular buffer.
 * FFT is only executed when the GUI asks for new FFT data via get_fft_data().
 */
int rx_fft_c::work(int noutput_items,
                   gr_vector_const_void_star &input_items,
                   gr_vector_void_star &output_items)
{
    int i;
    const gr_complex *in = (const gr_complex*)input_items[0];
    (void) output_items;

    /* just throw new samples into the buffer */
    boost::mutex::scoped_lock lock(d_mutex);

    int fftcount = d_fftsize/2; // 50% overlap

    for (i = 0; i < noutput_items; i++)
    {
        d_cbuf.push_back(in[i]);
        if(d_fftmode >= 1 && --fftcounter <= 0 && d_cbuf.size() >= d_fftsize) {
            fftcounter = fftcount;

            do_fft(d_cbuf.linearize(), d_fftsize);
            const gr_complex *ob = d_fft->get_outbuf();

            if(d_fftmode == 1) { // average
                for(unsigned int s=0; s<d_fftsize; s++) {
                    gr_complex c = ob[s];
                    averager[s] += c.real()*c.real() + c.imag()*c.imag();
                }
                averagecount++;
            } else { // peak
                for(unsigned int s=0; s<d_fftsize; s++) {
                    gr_complex c = ob[s];
                    float power = c.real()*c.real() + c.imag()*c.imag();
                    if(power > averager[s]) averager[s] = power;
                }
                averagecount = 1;
            }
        }
    }

    return noutput_items;

}
Esempio n. 6
0
/*! \brief Get FFT data.
 *  \param fftPoints Buffer to copy FFT data
 *  \param fftSize Current FFT size (output).
 */
void rx_fft_f::get_fft_data(std::complex<float>* fftPoints, unsigned int &fftSize)
{
    boost::mutex::scoped_lock lock(d_mutex);

    if (d_cbuf.size() < d_fftsize)
    {
        // not enough samples in the buffer
        fftSize = 0;

        return;
    }

    /* perform FFT */
    do_fft(d_cbuf.linearize(), d_cbuf.size());  // FIXME: array_one() and two() may be faster
    //d_cbuf.clear();

    /* get FFT data */
    memcpy(fftPoints, d_fft->get_outbuf(), sizeof(gr_complex)*d_fftsize);
    fftSize = d_fftsize;
}
Esempio n. 7
0
int main(int argc, char **argv)
{
	SNDFILE *file1, *file2;
	SF_INFO info1, info2;
	double *in1, *in2;
	int min_frames, i;
	int like = 0, unlike = 0;
	int total = 0;
	int max1, max2;
	struct fft_average *avg;

	memset(&info1, 0, sizeof(SF_INFO));
	memset(&info2, 0, sizeof(SF_INFO));

	if (argc < 3) {
		printf("compare file1 file2");
		return 1;
	}

	file1 = sf_open(argv[1], SFM_READ, &info1);
	if (!file1) {
		printf("Error opening wave file %s\n", argv[1]);
		exit(1);
	}

	file2 = sf_open(argv[2], SFM_READ, &info2);
	if (!file2) {
		printf("Error opening wave file %s\n", argv[2]);
		sf_close(file2);
		exit(1);
	}

/*
	seconds = (float)info1.frames/(float)info1.samplerate;
	printf("Opened %s\n", argv[1]);
	printf("frames: %d\n", info1.frames);
	printf("samplerate: %d\n", info1.samplerate);
	printf("length (in seconds): %f\n", seconds);
	printf("channels: %d\n", info1.channels);
	printf("format: %x\n", info1.format);
	printf("sections: %d\n", info1.sections);
	printf("seekable: %d\n", info1.seekable);
*/

	in1 = (double *)malloc(sizeof(double) * info1.frames);
	if (!in1) {
		printf("Failed to allocate input array\n");
		sf_close(file1);
		sf_close(file2);
		return 1;
	}

	in2 = (double *)malloc(sizeof(double) * info2.frames);
	if (!in2) {
		printf("Failed to allocate input array\n");
		free(in1);
		sf_close(file1);
		sf_close(file2);
		return 1;
	}

	normalize_wave(file1, in1, info1.frames, info1.channels);
	normalize_wave(file2, in2, info2.frames, info2.channels);
	max1 = shift_wave(in1, info1.frames);
	max2 = shift_wave(in2, info2.frames);
//	max1 = find_max(in1, info1.frames);
//	max2 = find_max(in2, info2.frames);
/*
	shift_wave(in1, info1.frames);
	shift_wave(in2, info2.frames);
*/
	plsdev("xwin");
	plinit();
	plenv(0.0f, info1.frames, -1, 1, 0, 0);
	for (i = 0; i < info1.frames; i++) {
		PLFLT x;
		PLFLT sample = i;
		if (in1[i] == -2)
			continue;
		x = in1[i];
		plpoin(1, &sample, &x, 1);		
	}
	plend();
	
	plsdev("xwin");
	plinit();
	plenv(0.0f, info2.frames, -1, 1, 0, 0);
	for (i = 0; i < info2.frames; i++) {
		PLFLT x;
		PLFLT sample = i;

		if (in2[i] == -2)
			continue;
		x = in2[i];
		plpoin(1, &sample, &x, 1);		
	}
	plend();

	avg = do_fft(in1, max1);
	printf("yavg = %f, xavg=%f\n", avg->yavg, avg->xavg);
	free(avg);
	avg = do_fft(in2, max2);
	printf("yavg = %f, xavg=%f\n", avg->yavg, avg->xavg);
	free(avg);
	min_frames = (info1.frames < info2.frames) ? info1.frames : info2.frames;

	for (i = 0; i < min_frames; i++) {
		double diff;

		if (in1[i] == -2 || in2[i] == -2)
			break;

		if (in1[i] > in2[i])
			diff = in1[i] - in2[i];
		else
			diff = in2[i] - in1[i];

		if (diff <= 0.05)
			like++;
		else
			unlike++;
		total++;
	}

	printf("Minimum frames: %d\n", min_frames);
	printf("Total compares: %d\n", total);
	printf("Like: %d\n", like);
	printf("Unlike: %d\n", unlike);
	printf("Percentage alike: %f\n", ((double)like / (double)total) * 100);
	printf("Max1: %d\n", max1);
	printf("Max2: %d\n", max2);

	free(in1);
	free(in2);
	sf_close(file1);
	sf_close(file2);

	return 0;
}
Esempio n. 8
0
//static int threshold = -60;
void sanalyzer_render_freq (gint16 /*in_data*/[])
{
#if 0
  gint i, c;
  gint y;
  gint16 freq_data[1024];
  static int fl = 0;

#ifdef DEBUG
struct timeval tv1, tv2;
gettimeofday (&tv1, NULL);
#endif
  do_fft (freq_data, in_data);

  CVFD::getInstance ()->Clear ();
#ifdef DEBUG
//gettimeofday (&tv1, NULL);
#endif
  for (i = 0; i < NUM_BANDS; i++) {
	y = 0;

#if 0 // using max value
        for (c = xscale[i]; c < xscale[i + 1]; c++) {
          if(freq_data[c] > threshold) {
            int val = freq_data[c]-threshold;
            if (val > y)
                y = val;
          }
        }
#else
        int val = 0;
        int cnt = 0;
        for (c = xscale[i]; c < xscale[i + 1]; c++) {
          if(freq_data[c] > threshold) {
            val += freq_data[c]-threshold;
            cnt++;
          }
        }
        if(cnt) y = val/cnt;
#endif

	if (y > HEIGHT - 1)
		y = HEIGHT - 1;

	if (y > bar_heights[i])
	  bar_heights[i] = y;
	else if (bar_heights[i] > FALL)
	  bar_heights[i] -= FALL;
	else
	  bar_heights[i] = 0;

	if (y > falloffs[i])
	  falloffs[i] = y;
	else if (falloffs[i] > FALLOFF) {
		fl ++;
		if(fl > 2) {
			fl = 0;
			falloffs[i] -= FALLOFF;
		}
	}
	else
	  falloffs[i] = 0;
  	CVFD::getInstance ()->drawBar (i*WIDTH, 64-falloffs[i]-5, WIDTH, 2);
	y = bar_heights[i];
  	CVFD::getInstance ()->drawBar (i*WIDTH, 64-y, WIDTH, y);
  }

#ifdef DEBUG
gettimeofday (&tv2, NULL);
printf("Calc takes %dns\n", (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec));
#endif
  CVFD::getInstance ()->Update ();
#endif
}
Esempio n. 9
0
int main( int argc, char **argv )
{
    if ( use_gui )
    {
        printf("init_sdl()\n");
        if ( init_sdl() ) return 1;

        printf("init_gl()\n");
        init_gl();
    }

    printf("init_fft()\n");
    init_fft();

#ifdef USE_FIFO
    printf("init_mpd()\n");
    if ( init_mpd() ) return 1;
#endif
#ifdef USE_ALSA
    printf("init_alsa()\n");
    if ( init_alsa() ) return 1;
#endif

    if ( use_serial )
    {
        printf("init_serial()\n");
        if ( init_serial() ) use_serial = FALSE;
    }

    init_lights();
    init_table();

    pthread_t sample_thread;

    pthread_create(&sample_thread, NULL, &get_samples, NULL);

    while ( !done )
    {

        // check to see if we have a new sample
        if (new_sample == 1)
        {
            // we are going to process this sample, it is no longer new
            pthread_mutex_lock(&sample_mutex);
            new_sample = 0;
            pthread_mutex_unlock(&sample_mutex);

            do_fft();

            detect_beats();

            assign_lights();

            //assign_cells();

            if ( use_gui )
            {
                if (handle_sdl_events()) return 1;
                draw_all();
            }

            if ( use_serial ) send_serial_fpga();
        }

        usleep(5000);
    }

    return 0;
}
Esempio n. 10
0
static gboolean
spectrogram_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data) {
    w_spectrogram_t *w = user_data;
    GtkAllocation a;
    gtk_widget_get_allocation (widget, &a);
    if (!w->samples || a.height < 1) {
        return FALSE;
    }

    int width, height;
    width = a.width;
    height = a.height;
    int ratio = ftoi (FFT_SIZE/(a.height*2));
    ratio = CLAMP (ratio,0,1023);

    if (deadbeef->get_output ()->state () == OUTPUT_STATE_PLAYING) {
        do_fft (w);
        float log_scale = (log2f(w->samplerate/2)-log2f(25.))/(a.height);
        float freq_res = w->samplerate / FFT_SIZE;

        if (a.height != w->height) {
            w->height = MIN (a.height, MAX_HEIGHT);
            for (int i = 0; i < w->height; i++) {
                w->log_index[i] = ftoi (powf(2.,((float)i) * log_scale + log2f(25.)) / freq_res);
                if (i > 0 && w->log_index[i-1] == w->log_index [i]) {
                    w->low_res_end = i;
                }
            }
        }
    }

    // start drawing
    if (!w->surf || cairo_image_surface_get_width (w->surf) != a.width || cairo_image_surface_get_height (w->surf) != a.height) {
        if (w->surf) {
            cairo_surface_destroy (w->surf);
            w->surf = NULL;
        }
        w->surf = cairo_image_surface_create (CAIRO_FORMAT_RGB24, a.width, a.height);
    }

    cairo_surface_flush (w->surf);

    unsigned char *data = cairo_image_surface_get_data (w->surf);
    if (!data) {
        return FALSE;
    }
    int stride = cairo_image_surface_get_stride (w->surf);

    if (deadbeef->get_output ()->state () == OUTPUT_STATE_PLAYING) {
        for (int i = 0; i < a.height; i++) {
            // scrolling: move line i 1px to the left
            memmove (data + (i*stride), data + sizeof (uint32_t) + (i*stride), stride - sizeof (uint32_t));
        }

        for (int i = 0; i < a.height; i++)
        {
            float f = 1.0;
            int index0, index1;
            int bin0, bin1, bin2;
            if (CONFIG_LOG_SCALE) {
                bin0 = w->log_index[CLAMP (i-1,0,height-1)];
                bin1 = w->log_index[i];
                bin2 = w->log_index[CLAMP (i+1,0,height-1)];
            }
            else {
                bin0 = (i-1) * ratio;
                bin1 = i * ratio;
                bin2 = (i+1) * ratio;
            }

            index0 = bin0 + ftoi ((bin1 - bin0)/2.f);
            if (index0 == bin0) index0 = bin1;
            index1 = bin1 + ftoi ((bin2 - bin1)/2.f);
            if (index1 == bin2) index1 = bin1;

            index0 = CLAMP (index0,0,FFT_SIZE/2-1);
            index1 = CLAMP (index1,0,FFT_SIZE/2-1);

            f = spectrogram_get_value (w, index0, index1);
            float x = 10 * log10f (f);

            // interpolate
            if (i <= w->low_res_end && CONFIG_LOG_SCALE) {
                int j = 0;
                // find index of next value
                while (i+j < height && w->log_index[i+j] == w->log_index[i]) {
                    j++;
                }
                float v0 = x;
                float v1 = w->data[w->log_index[i+j]];
                if (v1 != 0) {
                    v1 = 10 * log10f (v1);
                }

                int k = 0;
                while ((k+i) >= 0 && w->log_index[k+i] == w->log_index[i]) {
                    j++;
                    k--;
                }
                x = linear_interpolate (v0,v1,(1.0/(j-1)) * ((-1 * k) - 1));
            }

            // TODO: get rid of hardcoding 
            x += CONFIG_DB_RANGE - 63;
            x = CLAMP (x, 0, CONFIG_DB_RANGE);
            int color_index = GRADIENT_TABLE_SIZE - ftoi (GRADIENT_TABLE_SIZE/(float)CONFIG_DB_RANGE * x);
            color_index = CLAMP (color_index, 0, GRADIENT_TABLE_SIZE-1);
            _draw_point (data, stride, width-1, height-1-i, w->colors[color_index]);
        }
    }
    cairo_surface_mark_dirty (w->surf);

    cairo_save (cr);
    cairo_set_source_surface (cr, w->surf, 0, 0);
    cairo_rectangle (cr, 0, 0, a.width, a.height);
    cairo_fill (cr);
    cairo_restore (cr);

    return FALSE;
}