-WaveView::CacheEntry::CacheEntry (WaveView const * wave_view, double pixel_start, double pixel_end,
- framepos_t sample_start,framepos_t sample_end)
- : _wave_view (wave_view)
- , _pixel_start (pixel_start)
- , _pixel_end (pixel_end)
- , _sample_start (sample_start)
- , _sample_end (sample_end)
- , _n_peaks (_pixel_end - _pixel_start)
-{
- _peaks.reset (new PeakData[_n_peaks]);
-
- _wave_view->_region->read_peaks (_peaks.get(), _n_peaks,
- _sample_start, _sample_end - _sample_start,
- _wave_view->_channel,
- _wave_view->_samples_per_pixel);
-}
-
-WaveView::CacheEntry::~CacheEntry ()
-{
-}
-
-static inline float
-_log_meter (float power, double lower_db, double upper_db, double non_linearity)
-{
- return (power < lower_db ? 0.0 : pow((power-lower_db)/(upper_db-lower_db), non_linearity));
-}
-
-static inline float
-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<Cairo::ImageSurface>
-WaveView::CacheEntry::image ()
-{
- if (!_image) {
-
- _image = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, _n_peaks, _wave_view->_height);
- Cairo::RefPtr<Cairo::Context> context = Cairo::Context::create (_image);
-
-#ifdef AREA_DRAW_AND_FILL
-
- /* Draw the edge of the waveform, top half first, the loop back
- * for the bottom half to create a clockwise path
- */
-
- context->begin_new_path();
-
- if (_wave_view->_shape == WaveView::Rectified) {
-
- /* top edge of waveform is based on max (fabs (peak_min, peak_max))
- */
-
- if (_wave_view->_logscaled) {
- for (int i = 0; i < _n_peaks; ++i) {
- context->line_to (i + 0.5, 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) {
- context->line_to (i + 0.5, position (max (fabs (_peaks[i].max), fabs (_peaks[i].min))));
- }
- }
-
- } else {
- if (_wave_view->_logscaled) {
- for (int i = 0; i < _n_peaks; ++i) {
- Coord y = _peaks[i].max;
-
- if (y > 0.0) {
- y = position (alt_log_meter (fast_coefficient_to_dB (y)));
- } else if (y < 0.0) {
- y = position (-alt_log_meter (fast_coefficient_to_dB (-y)));
- } else {
- y = position (0.0);
- }
- context->line_to (i + 0.5, y);
- }
- } else {
- for (int i = 0; i < _n_peaks; ++i) {
- context->line_to (i + 0.5, position (_peaks[i].max));
- }
- }
- }
-
- /* from final top point, move out of the clip zone */
-
- context->line_to (_n_peaks + 10, position (0.0));
-
- /* bottom half, in reverse */
-
- if (_wave_view->_shape == WaveView::Rectified) {
-
- /* lower half: drop to the bottom, then a line back to
- * beyond the left edge of the clip region
- */
-
- context->line_to (_n_peaks + 10, _wave_view->_height);
- context->line_to (-10.0, _wave_view->_height);
-
- } else {
-
- if (_wave_view->_logscaled) {
- for (int i = _n_peaks-1; i >= 0; --i) {
- Coord y = _peaks[i].min;
- if (y > 0.0) {
- context->line_to (i + 0.5, position (alt_log_meter (fast_coefficient_to_dB (y))));
- } else if (y < 0.0) {
- context->line_to (i + 0.5, position (-alt_log_meter (fast_coefficient_to_dB (-y))));
- } else {
- context->line_to (i + 0.5, position (0.0));
- }
- }
- } else {
- for (int i = _n_peaks-1; i >= 0; --i) {
- context->line_to (i + 0.5, position (_peaks[i].min));
- }
- }
-
- /* from final bottom point, move out of the clip zone */
-
- context->line_to (-10.0, position (0.0));
- }
-
- context->close_path ();
-
- if (_wave_view->gradient_depth() != 0.0) {
-
- Cairo::RefPtr<Cairo::LinearGradient> 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 */
- s *= 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 {
- set_source_rgba (context, _wave_view->_fill_color);
- }
-
- context->fill_preserve ();
- _wave_view->setup_outline_context (context);
- context->stroke ();
-
-#else
- boost::scoped_array<LineTips> 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 = position (_peaks[i].min);
- tips[i].bot = position (_peaks[i].max);
- }
- }
- }
-
- if (_wave_view->gradient_depth() != 0.0) {
-
- Cairo::RefPtr<Cairo::LinearGradient> 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);
- /* change v towards white */
- 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 {
- set_source_rgba (context, _wave_view->_fill_color);
- }
-
- /* ensure single-pixel lines */
-
- context->set_line_width (0.5);
- context->translate (0.5, 0.0);
-
- /* draw the lines */
-
- if (_wave_view->_shape == WaveView::Rectified) {
- for (int i = 0; i < _n_peaks; ++i) {
- context->move_to (i, tips[i].top); /* down 1 pixel */
- context->line_to (i, tips[i].bot);
- context->stroke ();
- }
- } else {
- for (int i = 0; i < _n_peaks; ++i) {
- context->move_to (i, tips[i].top);
- context->line_to (i, tips[i].bot);
- 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_rgba (0, 0, 0, 1.0);
-
- for (int i = 0; i < _n_peaks; ++i) {
- context->move_to (i, tips[i].top);
- context->rel_line_to (0, 1.0);
- context->stroke ();
- if (_wave_view->_shape != WaveView::Rectified) {
- context->move_to (i, tips[i].bot);
- context->rel_line_to (0, -1.0);
- context->stroke ();
- }
- }
-#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 ();
- }
-
- }
-
- return _image;
-}
-
-