From 1c74a3ab2da2de7b4e0df177d76cdb5cc695c7bd Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 21 Jun 2013 13:17:37 -0400 Subject: [PATCH] waveform drawing improvements * handle logscaled and rectified * put dark tips in right places * improve color selection algorithm --- gtk2_ardour/audio_region_view.cc | 19 ++-- libs/canvas/wave_view.cc | 161 +++++++++++++++++++++++++++---- 2 files changed, 153 insertions(+), 27 deletions(-) diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index 6ee30ea912..47aebb765f 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -1194,13 +1194,21 @@ AudioRegionView::create_one_wave (uint32_t which, bool /*direct*/) } else { wave->set_outline_color (_region->muted() ? UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->get_canvasvar_WaveForm(), MUTED_ALPHA) : ARDOUR_UI::config()->get_canvasvar_WaveForm()); + /* wave color is a saturated, whiter version of the frame's + * fill color + */ + ArdourCanvas::Color c = frame->fill_color (); double h, s, v; ArdourCanvas::color_to_hsv (c, h, s, v); - v *= 0.5; - c = ArdourCanvas::hsv_to_color (h, s, v, 1.0); - //wave->set_fill_color (ARDOUR_UI::config()->get_canvasvar_WaveFormFill()); + /* full saturate */ + s = 1.0; + /* head towards white */ + v = min (1.0, v * 3.0); + + c = ArdourCanvas::hsv_to_color (h, s, v, _region->muted() ? MUTED_ALPHA : 1.0); + wave->set_fill_color (c); } @@ -1343,12 +1351,9 @@ AudioRegionView::setup_waveform_shape () void AudioRegionView::setup_waveform_scale () { - for (vector::iterator wave = waves.begin(); wave != waves.end() ; ++wave) { - (*wave)->set_logscaled (Config->get_waveform_scale() == Logarithmic); - } + WaveView::set_global_logscaled (Config->get_waveform_scale() == Logarithmic); } - GhostRegion* AudioRegionView::add_ghost (TimeAxisView& tv) { diff --git a/libs/canvas/wave_view.cc b/libs/canvas/wave_view.cc index 5850d0ed99..ead80f7cbf 100644 --- a/libs/canvas/wave_view.cc +++ b/libs/canvas/wave_view.cc @@ -21,6 +21,8 @@ #include #include +#include + #include "gtkmm2ext/utils.h" #include "pbd/compose.h" @@ -388,7 +390,6 @@ WaveView::set_global_logscaled (bool yn) if (_global_logscaled != yn) { _global_logscaled = yn; VisualPropertiesChanged (); /* EMIT SIGNAL */ - } } @@ -458,6 +459,14 @@ alt_log_meter (float power) return _log_meter (power, -192.0, 0.0, 8.0); } +struct LineTips { + double top; + double bot; + bool clipped; + + LineTips() : top (0.0), bot (0.0), clipped (false) {} +}; + Cairo::RefPtr WaveView::CacheEntry::image () { @@ -592,32 +601,144 @@ WaveView::CacheEntry::image () _wave_view->setup_outline_context (context); context->stroke (); +#else + cerr << "draw, logscaled = " << _wave_view->_logscaled << " global " << WaveView::_global_logscaled << endl; + + boost::scoped_array tips (new LineTips[_n_peaks]); + + if (_wave_view->_shape == WaveView::Rectified) { + + /* each peak is a line from the bottom of the waveview + * to a point determined by max (_peaks[i].max, + * _peaks[i].min) + */ + + if (_wave_view->_logscaled) { + for (int i = 0; i < _n_peaks; ++i) { + tips[i].bot = _wave_view->height(); + tips[i].top = position (alt_log_meter (fast_coefficient_to_dB (max (fabs (_peaks[i].max), fabs (_peaks[i].min))))); + } + } else { + for (int i = 0; i < _n_peaks; ++i) { + tips[i].bot = _wave_view->height(); + tips[i].top = position (max (fabs (_peaks[i].max), fabs (_peaks[i].min))); + } + } + + } else { + + if (_wave_view->_logscaled) { + for (int i = 0; i < _n_peaks; ++i) { + Coord top = _peaks[i].min; + Coord bot = _peaks[i].max; + + if (top > 0.0) { + top = position (alt_log_meter (fast_coefficient_to_dB (top))); + } else if (top < 0.0) { + top = position (-alt_log_meter (fast_coefficient_to_dB (-top))); + } else { + top = position (0.0); + } + + if (bot > 0.0) { + bot = position (alt_log_meter (fast_coefficient_to_dB (bot))); + } else if (bot < 0.0) { + bot = position (-alt_log_meter (fast_coefficient_to_dB (-bot))); + } else { + bot = position (0.0); + } + + tips[i].top = top; + tips[i].bot = bot; + + } + + } else { + for (int i = 0; i < _n_peaks; ++i) { + tips[i].top = floor (position (_peaks[i].min)); + tips[i].bot = ceil (position (_peaks[i].max)); + } + } + } + + if (_wave_view->gradient_depth() != 0.0) { + + Cairo::RefPtr gradient (Cairo::LinearGradient::create (0, 0, 0, _wave_view->_height)); + + double stops[3]; + + double r, g, b, a; + + if (_wave_view->_shape == Rectified) { + stops[0] = 0.1; + stops[0] = 0.3; + stops[0] = 0.9; + } else { + stops[0] = 0.1; + stops[1] = 0.5; + stops[2] = 0.9; + } + + color_to_rgba (_wave_view->_fill_color, r, g, b, a); + gradient->add_color_stop_rgba (stops[0], r, g, b, a); + gradient->add_color_stop_rgba (stops[2], r, g, b, a); + + /* generate a new color for the middle of the gradient */ + double h, s, v; + color_to_hsv (_wave_view->_fill_color, h, s, v); + /* tone down the saturation */ + v *= 1.0 - _wave_view->gradient_depth(); + Color center = hsv_to_color (h, s, v, a); + color_to_rgba (center, r, g, b, a); + gradient->add_color_stop_rgba (stops[1], r, g, b, a); + + context->set_source (gradient); + } else { + cerr << "\tno gradient\n"; + set_source_rgba (context, _wave_view->_fill_color); + } + + context->set_line_width (0.5); + + /* draw the lines */ + + if (_wave_view->_shape == WaveView::Rectified) { + for (int i = 0; i < _n_peaks; ++i) { + context->move_to (i + 0.5, tips[i].top + 0.5); /* down 1 pixel */ + context->line_to (i + 0.5, tips[i].bot); + context->stroke (); + } + } else { + for (int i = 0; i < _n_peaks; ++i) { + context->move_to (i + 0.5, tips[i].top + 0.5); /* down 1 pixel */ + context->line_to (i + 0.5, tips[i].bot - 0.5); /* up 1 pixel */ + context->stroke (); + } + } + + /* now add dots to the top and bottom of each line (this is + * modelled on pyramix, except that we add clipping indicators. + */ + + context->set_source_rgb (0, 0, 0); + + for (int i = 0; i < _n_peaks; ++i) { + context->rectangle (i + 0.5, tips[i].top, 0.5, 0.5); + context->fill (); + if (_wave_view->_shape != WaveView::Rectified) { + context->rectangle (i + 0.5, tips[i].bot, 0.5, 0.5); + context->fill (); + } + } +#endif + if (_wave_view->show_zero_line()) { set_source_rgba (context, _wave_view->_zero_color); context->move_to (0, position (0.0)); context->line_to (_n_peaks, position (0.0)); context->stroke (); } -#else - - set_source_rgba (context, _wave_view->_fill_color); - context->save (); - context->set_line_width (0.5); - for (int i = 0; i < _n_peaks; ++i) { - context->move_to (i + 0.5, floor (position (_peaks[i].min)) - 1.0); - context->line_to (i + 0.5, ceil (position (_peaks[i].max)) + 1.0); - context->stroke (); - } - context->restore (); - context->set_source_rgba (0, 0, 0, 1.0); - for (int i = 0; i < _n_peaks; ++i) { - context->rectangle (i + 0.5, floor (position (_peaks[i].min)), 0.5, 0.5); - context->fill (); - context->rectangle (i + 0.5, ceil (position (_peaks[i].max)), 0.5, 0.5); - context->fill (); - } -#endif } return _image;