Esempio n. 1
2
static void plot_data_fft(SFSUI* ui) {
	cairo_t* cr;
	cr = cairo_create (ui->sf_dat);

	rounded_rectangle (cr, SS_BORDER, SS_BORDER, SS_SIZE, SS_SIZE, SS_BORDER);
	cairo_clip_preserve (cr);

	const float persistence = robtk_dial_get_value(ui->screen);
	float transp;
	cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
	if (persistence > 0) {
		cairo_set_source_rgba(cr, 0, 0, 0, .25 - .0025 * persistence);
		transp = 0.05;
	} else {
		cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
		transp = .5;
	}
	cairo_fill(cr);

	cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
	cairo_set_line_width (cr, 1.0);

	const float xmid = rintf(SS_BORDER + SS_SIZE *.5) + .5;
	const float dnum = SS_SIZE / ui->log_base;
	const float denom = ui->log_rate / (float)ui->fft_bins;

	cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
	for (uint32_t i = 1; i < ui->fft_bins-1 ; ++i) {
		if (ui->level[i] < 0) continue;

		const float level = MAKEUP_GAIN + fftx_power_to_dB(ui->level[i]);
		if (level < -80) continue;

		const float y  = rintf(SS_BORDER + SS_SIZE - dnum * fast_log10(1.0 + i * denom)) + .5;
		const float y1 = rintf(SS_BORDER + SS_SIZE - dnum * fast_log10(1.0 + (i+1) * denom)) + .5;
		const float pk = level > 0.0 ? 1.0 : (80 + level) / 80.0;
		const float a_lr = ui->lr[i];

		float clr[3];
		hsl2rgb(clr, .70 - .72 * pk, .9, .3 + pk * .4);
		cairo_set_source_rgba(cr, clr[0], clr[1], clr[2], transp  + pk * .2);
		cairo_set_line_width (cr, MAX(1.0, (y - y1)));

		cairo_move_to(cr, xmid, y);
		cairo_line_to(cr, SS_BORDER + SS_SIZE * a_lr, y);
		cairo_stroke(cr);

	}
	cairo_destroy (cr);
}
Esempio n. 2
0
/* linear FFT data display */
static void plot_data_fft(MF2UI* ui) {
	cairo_t* cr;
	const double ccc = ui->width / 2.0 + .5;
	const double rad = (ui->width - XOFF) * .5;
	const float gain = robtk_dial_get_value(ui->gain);
	const float persistence = robtk_dial_get_value(ui->screen);

	cr = cairo_create (ui->sf_dat);
	cairo_arc (cr, ccc, ccc, rad, 0, 2.0 * M_PI);
	cairo_clip_preserve (cr);

	cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
	if (persistence > 0) {
		cairo_set_source_rgba(cr, 0, 0, 0, .3 - .003 * persistence);
	} else {
		cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
	}
	cairo_fill(cr);
	cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
	const float dnum = ui->scale * PH_RAD / ui->log_base;
	const float denom = ui->log_rate / (float)ui->fft_bins;
	const float cutoff = ui->db_cutoff;
	for (uint32_t i = 1; i < ui->fft_bins-1 ; ++i) {
		if (ui->level[i] < 0) continue;
		const float level = gain + fftx_power_to_dB(ui->level[i]);
		if (level < cutoff) continue;

		const float dist = dnum * fast_log10(1.0 + i * denom);
		const float dx = ccc + dist * sinf(ui->phase[i]);
		const float dy = ccc - dist * cosf(ui->phase[i]);
		const float pk = level > 0.0 ? 1.0 : (cutoff - level) / cutoff;

		draw_point(ui, cr, pk, dx, dy, ccc, dist, ui->phase[i]);
	}
	cairo_destroy (cr);
}
Esempio n. 3
0
static void process_audio(MF2UI* ui, const size_t n_elem, float const * const left, float const * const right) {
	pthread_mutex_lock(&ui->fft_lock);

	fftx_run(ui->fa, n_elem, left);
	bool display = !fftx_run(ui->fb, n_elem, right);

	if (display) {
		assert (fftx_bins(ui->fa) == ui->fft_bins);
		float peak = 0;
		const float db_thresh = ui->db_thresh;
		for (uint32_t i = 1; i < ui->fft_bins-1; i++) {
			if (ui->fa->power[i] < db_thresh || ui->fb->power[i] < db_thresh) {
				ui->phase[i] = 0;
				ui->level[i] = -100;
				continue;
			}
			const float phase0 = ui->fa->phase[i];
			const float phase1 = ui->fb->phase[i];
			float phase = phase1 - phase0;
			ui->phase[i] = phase;
			ui->level[i] = MAX(ui->fa->power[i], ui->fb->power[i]);
			if (ui->level[i] > peak) {
				peak = ui->level[i];
			}
		}

		ui->peak += .04 * (peak - ui->peak) + 1e-15;
		if (isnan (ui->peak)) { ui->peak = 0; }
		if (ui->peak > 1000) { ui->peak = 1000; }
		if (robtk_cbtn_get_active(ui->btn_norm)) {
			robtk_dial_set_value(ui->gain, - fftx_power_to_dB(ui->peak));
		}
		queue_draw(ui->m0);
	}
	pthread_mutex_unlock(&ui->fft_lock);
}
Esempio n. 4
0
static void plot_data_oct(SFSUI* ui) {
	cairo_t* cr;
	cr = cairo_create (ui->sf_dat);
	rounded_rectangle (cr, SS_BORDER, SS_BORDER, SS_SIZE, SS_SIZE, SS_BORDER);
	cairo_clip_preserve (cr);

	const float persistence = robtk_dial_get_value(ui->screen);
	cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
	if (persistence > 0) {
		cairo_set_source_rgba(cr, 0, 0, 0, .33 - .0033 * persistence);
	} else {
		cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
	}
	cairo_fill(cr);
	cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);

	const float xmid = rintf(SS_BORDER + SS_SIZE *.5) + .5;
	const float dnum = SS_SIZE / ui->log_base;
	const float denom = 2.0 * ui->log_rate / ui->rate;

	uint32_t fi = 1;
	for (uint32_t i = 0; i < ui->freq_bins; ++i) {
		float a_lr = 0;
		float a_level = 0;
		float a_freq = 0;
		uint32_t a_cnt = 0;

		while(fi < ui->freq_band[i]) {
			if (ui->level[fi] < 0) { fi++; continue; }

			a_freq += fi * ui->fa->freq_per_bin;
			a_level += ui->level[fi];
			a_lr += ui->lr[fi];
			a_cnt++;
			fi++;
		}
		if (a_cnt == 0) continue;
		a_level = MAKEUP_GAIN + fftx_power_to_dB (a_level);
		if (a_level < -80) continue;

		a_freq /= (float)a_cnt;
		a_lr /= (float)a_cnt;

		const float y = rintf(SS_BORDER + SS_SIZE - dnum * fast_log10(1.0 + a_freq * denom)) + .5;
		const float pk = a_level > 0.0 ? 1.0 : (80 + a_level) / 80.0;

		float clr[3];
		hsl2rgb(clr, .70 - .72 * pk, .9, .3 + pk * .4);
		cairo_set_source_rgba(cr, clr[0], clr[1], clr[2], 0.8);

		if (fabsf(a_lr -.5) < .05) {
			cairo_set_line_width (cr, 3.0);
		} else {
			cairo_set_line_width (cr, 1.0);
		}

		cairo_move_to(cr, xmid, y);
		cairo_line_to(cr, SS_BORDER + SS_SIZE * a_lr, y);
		cairo_stroke(cr);
	}
	cairo_destroy (cr);
}
Esempio n. 5
0
FFTX_FN_PREFIX
float fftx_power_at_bin(struct FFTAnalysis *ft, const int b) {
	return (fftx_power_to_dB(ft->power[b]));
}
Esempio n. 6
0
/* 1/Octave data display */
static void plot_data_oct(MF2UI* ui) {
	cairo_t* cr;
	const double ccc = ui->width / 2.0 + .5;
	const double rad = (ui->width - XOFF) * .5;
	const float gain = robtk_dial_get_value(ui->gain);
	const float persistence = robtk_dial_get_value(ui->screen);

	cr = cairo_create (ui->sf_dat);
	cairo_arc (cr, ccc, ccc, rad, 0, 2.0 * M_PI);
	cairo_clip_preserve (cr);

	cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
	if (persistence > 0) {
		cairo_set_source_rgba(cr, 0, 0, 0, .33 - .0033 * persistence);
	} else {
		cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
	}
	cairo_fill(cr);
	cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);

	const float dnum = ui->scale * PH_RAD / ui->log_base;
	const float denom = 2.0 * ui->log_rate / ui->rate;
	const float cutoff = ui->db_cutoff;

	uint32_t fi = 1;
	for (uint32_t i = 0; i < ui->freq_bins; ++i) {
		float ang_x = 0;
		float ang_y = 0;
		float a_level = 0;
		float a_freq = 0;
		uint32_t a_cnt = 0;

		while(fi < ui->freq_band[i]) {
			if (ui->level[fi] < 0) { fi++; continue; }
			a_freq += fi * ui->fa->freq_per_bin;
			a_level += ui->level[fi];
			ang_x += sinf(ui->phase[fi]);
			ang_y += cosf(ui->phase[fi]);
			a_cnt++;
			fi++;
		}
		if (a_cnt == 0) continue;
		a_level = gain + fftx_power_to_dB (a_level);
		if (a_level < cutoff) continue;

		a_freq /= (float)a_cnt;
		const float dist = dnum * fast_log10(1.0 + a_freq * denom);
		const float pk = a_level > 0.0 ? 1.0 : (cutoff - a_level) / cutoff;

		float dx, dy;
		if (a_cnt == 1) {
			dx = ccc + dist * ang_x;
			dy = ccc - dist * ang_y;
		} else {
			const float phase = atan2f(ang_x, ang_y);
			dx = ccc + dist * sinf(phase);
			dy = ccc - dist * cosf(phase);
		}

		draw_point(ui, cr, pk, dx, dy, 0, 0, 0);
	}

	cairo_destroy (cr);
}