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); }
void TrackEffects::populateAuxForTrack(AudioTrack* t)/*{{{*/ { if (t && t->hasAuxSend()) { AuxProxy *proxy = new AuxProxy(t); int idx = 0; QHash<qint64, AuxInfo>::const_iterator iter = t->auxSends()->constBegin(); while (iter != t->auxSends()->constEnd()) { Track* at = song->findTrackByIdAndType(iter.key(), Track::AUDIO_AUX); if(at) { //qDebug("Adding AUX to strip: Name: %s, tid: %lld, auxId: %lld", at->name().toUtf8().constData(), at->id(), iter.key()); DoubleLabel* al; QLabel* nl; Knob* ak = addAuxKnob(proxy, iter.key(), at->name(), &al, &nl); proxy->auxIndexList[idx] = iter.key(); proxy->auxKnobList[iter.key()] = ak; proxy->auxLabelList[iter.key()] = al; proxy->auxNameLabelList[iter.key()] = nl; ak->setId(idx); al->setId(idx); double val = fast_log10(t->auxSend(iter.key()))*20.0; ak->setValue(val); al->setValue(val); ++idx; } ++iter; } m_proxy.insert(t->id(), proxy); } }/*}}}*/
void AbstractSlider::setMaxLogValue(double val) { if (_log) { _maxValue = fast_log10(val) * 20.0f; } else _maxValue = val; }
void AbstractSlider::setMinLogValue(double val) { if (_log) { if (val == 0.0f) _minValue = -100; else _minValue = fast_log10(val) * 20.0f; } else _minValue = val; }
void FloatEntry::setValue(double val) { if (_log) { if (val == 0.0f) _value = _minValue; else _value = fast_log10(val) * 20.0f; } else _value = val; updateValue(); }
static void process_audio(SFSUI* 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); const float db_thresh = 1e-20; 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->lr[i] = 0.5; ui->level[i] = 0; continue; } const float lv = MAX(ui->fa->power[i], ui->fb->power[i]); #if 1 const float lr = .5 + .5 * (sqrtf(ui->fb->power[i]) - sqrtf(ui->fa->power[i])) / sqrtf(lv); #else //XXX TODO log-scale / deflection of fraction //const float lr = .5 + .25 * fast_log10(ui->fb->power[i] / ui->fa->power[i]); float lr; if (ui->fb->power[i] < ui->fa->power[i]) { lr = .5 + .5 * fast_log10(ui->fb->power[i] / ui->fa->power[i]); } else { lr = .5 - .5 * fast_log10(ui->fa->power[i] / ui->fb->power[i]); } #endif ui->level[i] += .1 * (lv - ui->level[i]) + 1e-20; ui->lr[i] += .1 * (lr - ui->lr[i]) + 1e-10; } queue_draw(ui->m0); } pthread_mutex_unlock(&ui->fft_lock); }
void AbstractSlider::setValue(double val) { if (_log) { if (val == 0.0f) _value = _minValue; else { _value = fast_log10(val) * 20.0f; if (_value < _minValue) _value = _minValue; } } else _value = val; update(); }
/* 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); }
inline decibel::decibel(double val) : val(20.0f * fast_log10(val)) {}
double trackVolToDb(double vol) { return fast_log10(vol) * 20.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); }
void Mixer_Strip::set_rms_level(int _index, float _rms_level) { rms_level_n_1[_index] = rms_level[_index]; rms_level[_index] = att_rms_level * rms_level_n_1[_index] + (1.0 - att_rms_level) * fast_log10(_rms_level); if (rms_level[_index]>DB_VOL_MAX) rms_level[_index] = DB_VOL_MAX; if (rms_level[_index]<DB_VOL_MIN) rms_level[_index] = DB_VOL_MIN; coarseDial->setMeterVal(_index, rms_level[_index], max_level[_index]); }
/* 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); }
/** draw frequency calibration circles * and on screen annotations - sample-rate dependent */ static void update_grid(MF2UI* ui) { const double ccc = ui->width / 2.0 + .5; const double rad = (ui->width - XOFF) * .5; cairo_t *cr = cairo_create (ui->sf_ann); cairo_rectangle (cr, 0, 0, ui->width, ui->height); CairoSetSouerceRGBA(ui->c_bg); cairo_fill (cr); cairo_set_line_width (cr, 1.0); cairo_arc (cr, ccc, ccc, rad, 0, 2.0 * M_PI); cairo_set_source_rgba(cr, 0, 0, 0, 1.0); cairo_fill_preserve(cr); CairoSetSouerceRGBA(c_g90); cairo_stroke(cr); const double dash1[] = {1.0, 2.0}; cairo_set_dash(cr, dash1, 2, 0); CairoSetSouerceRGBA(c_grd); float freq = 62.5; while (freq < ui->rate / 2) { char txt[16]; if (freq < 1000) { snprintf(txt, 16, "%d Hz", (int)ceil(freq)); } else { snprintf(txt, 16, "%d KHz", (int)ceil(freq/1000.f)); } { const float dr = ui->scale * PH_RAD * fast_log10(1.0 + 2 * freq * ui->log_rate / ui->rate) / ui->log_base; cairo_arc (cr, ccc, ccc, dr, 0, 2.0 * M_PI); cairo_stroke(cr); const float px = ccc + dr * sinf(M_PI * -.75); const float py = ccc - dr * cosf(M_PI * -.75); write_text_full(cr, txt, ui->font[0], px, py, M_PI * -.75, -2, c_ahz); } freq *= 2.0; } const double dash2[] = {1.0, 3.0}; cairo_set_line_width(cr, 3.5); cairo_set_dash(cr, dash2, 2, 2); cairo_set_line_width(cr, 1.5); cairo_move_to(cr, ccc - rad, ccc); cairo_line_to(cr, ccc + rad, ccc); cairo_stroke(cr); cairo_set_line_width(cr, 3.5); cairo_move_to(cr, ccc, ccc - rad); cairo_line_to(cr, ccc, ccc + rad); cairo_stroke(cr); cairo_set_dash(cr, NULL, 0, 0); write_text_full(cr, "+L", ui->font[0], ccc, ccc - rad * .92, 0, -2, c_ann); write_text_full(cr, "-L", ui->font[0], ccc, ccc + rad * .92, 0, -2, c_ann); write_text_full(cr, "0\u00B0", ui->font[0], ccc, ccc - rad * .80, 0, -2, c_ann); write_text_full(cr, "180\u00B0", ui->font[0], ccc, ccc + rad * .80, 0, -2, c_ann); write_text_full(cr, "-R", ui->font[0], ccc - rad * .92, ccc, 0, -2, c_ann); write_text_full(cr, "+R", ui->font[0], ccc + rad * .92, ccc, 0, -2, c_ann); write_text_full(cr, "-90\u00B0", ui->font[0], ccc - rad * .80, ccc, 0, -2, c_ann); write_text_full(cr, "+90\u00B0", ui->font[0], ccc + rad * .80, ccc, 0, -2, c_ann); cairo_destroy (cr); }
FFTX_FN_PREFIX inline float fftx_power_to_dB(float a) { /* 10 instead of 20 because of squared signal -- no sqrt(powerp[]) */ return a > 1e-12 ? 10.0 * fast_log10(a) : -INFINITY; }
void MeterSlider::paintEvent(QPaintEvent* ev) { int h = height(); int kh = sliderSize().height(); int mh = h - kh; double range = maxValue() - minValue(); int ppos = int(mh * (_value - minValue()) / range); if (_invert) ppos = mh - ppos; QPainter p(this); p.setRenderHint(QPainter::Antialiasing, false); //--------------------------------------------------- // draw meter //--------------------------------------------------- int mw = _meterWidth / _channel; int x = 20; int y1 = kh / 2; int y3 = h - y1; p.setPen(QPen(Qt::white, 2)); for (int i = 0; i < _channel; ++i) { int h = mh - (lrint(fast_log10(meterval[i]) * -20.0f * mh / range)); if (h < 0) h = 0; else if (h > mh) h = mh; p.drawPixmap(x, y1+mh-h, mw, h, onPm, 0, mh-h, mw, h); p.drawPixmap(x, y1, mw, mh-h, offPm, 0, 0, mw, mh-h); //--------------------------------------------------- // draw peak line //--------------------------------------------------- h = mh - (lrint(fast_log10(meterPeak[i]) * -20.0f * mh / range)); if (h > mh) h = mh; if (h > 0) p.drawLine(x, y3-h, x+mw, y3-h); x += mw; } // optimize common case: if (ev->rect() == QRect(20, kh/2, _meterWidth-1, mh)) return; QColor sc(isEnabled() ? _scaleColor : Qt::gray); QColor svc(isEnabled() ? _scaleValueColor : Qt::gray); p.setBrush(svc); //--------------------------------------------------- // draw scale //--------------------------------------------------- int y2 = h - (ppos + y1); p.fillRect(x, y1, _scaleWidth, y2-y1, sc); p.fillRect(x, y2, _scaleWidth, y3-y2, svc); //--------------------------------------------------- // draw tick marks //--------------------------------------------------- QFont f(p.font()); f.setPointSize(6); p.setFont(f); p.setPen(QPen(Qt::darkGray, 2)); QFontMetrics fm(f); int xt = 20 - fm.width("00") - 5; QString s; for (int i = 10; i < 70; i += 10) { h = y1 + lrint(i * mh / range); s.setNum(i - 10); p.drawText(xt, h - 3, s); p.drawLine(15, h, 20, h); } //--------------------------------------------------- // draw slider //--------------------------------------------------- x += _scaleWidth/2; p.setPen(QPen(svc, 0)); p.translate(QPointF(x, y2)); p.setRenderHint(QPainter::Antialiasing, true); p.drawPath(*points); }
double CtrlList::value(int frame, bool cur_val_only, int* nextFrame) const { if(cur_val_only || empty()) { if(nextFrame) *nextFrame = -1; return _curVal; } double rv; int nframe; ciCtrl i = upper_bound(frame); // get the index after current frame if (i == end()) { // if we are past all items just return the last value --i; if(nextFrame) *nextFrame = -1; return i->second.val; } else if(_mode == DISCRETE) { if(i == begin()) { nframe = i->second.frame; rv = i->second.val; } else { nframe = i->second.frame; --i; rv = i->second.val; } } else { // INTERPOLATE if (i == begin()) { nframe = i->second.frame; rv = i->second.val; } else { int frame2 = i->second.frame; double val2 = i->second.val; --i; int frame1 = i->second.frame; double val1 = i->second.val; if(val2 != val1) nframe = 0; // Zero signifies the next frame should be determined by caller. else nframe = frame2; if (_valueType == VAL_LOG) { val1 = 20.0*fast_log10(val1); if (val1 < MusEGlobal::config.minSlider) val1=MusEGlobal::config.minSlider; val2 = 20.0*fast_log10(val2); if (val2 < MusEGlobal::config.minSlider) val2=MusEGlobal::config.minSlider; } val2 -= val1; val1 += (double(frame - frame1) * val2)/double(frame2 - frame1); if (_valueType == VAL_LOG) { val1 = exp10(val1/20.0); } rv = val1; } } if(nextFrame) *nextFrame = nframe; return rv; }
void MidiVolEntry::setValue(double v) { FloatEntry::setValue(-fast_log10(double(_max*_max)/(v*v))*20.0f); }