Compare commits
18 Commits
Author | SHA1 | Date |
---|---|---|
|
eec505621a | |
|
1990839728 | |
|
8a0404a545 | |
|
027f068d43 | |
|
0e8c07cbe9 | |
|
7c9cb6615c | |
|
e1ccb6d5d4 | |
|
621c905590 | |
|
f79238bebc | |
|
d6ded04b1d | |
|
b34f7d0ea0 | |
|
8549c99444 | |
|
6f01cc6232 | |
|
959ef3e762 | |
|
bf5bb1a07f | |
|
404fdae8af | |
|
dea2eb2326 | |
|
c72df7e24c |
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <glibmm/threads.h>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/scoped_array.hpp>
|
||||
|
||||
#include "ardour/source.h"
|
||||
#include "ardour/ardour.h"
|
||||
|
@ -164,6 +165,12 @@ class LIBARDOUR_API AudioSource : virtual public Source,
|
|||
framecnt_t peak_leftover_size;
|
||||
Sample* peak_leftovers;
|
||||
framepos_t peak_leftover_frame;
|
||||
|
||||
mutable uint32_t _last_map_off;
|
||||
mutable size_t _last_raw_map_length;
|
||||
mutable bool _first_run;
|
||||
mutable double _last_scale;
|
||||
mutable boost::scoped_array<PeakData> peak_cache;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -34,10 +34,11 @@
|
|||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
#include <glibmm/fileutils.h>
|
||||
|
@ -53,7 +54,7 @@
|
|||
#include "i18n.h"
|
||||
|
||||
#include "ardour/debug.h"
|
||||
|
||||
const int BUFSIZE = sysconf(_SC_PAGESIZE);
|
||||
using namespace std;
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
@ -78,6 +79,8 @@ AudioSource::AudioSource (Session& s, string name)
|
|||
, peak_leftover_cnt (0)
|
||||
, peak_leftover_size (0)
|
||||
, peak_leftovers (0)
|
||||
, _first_run (true)
|
||||
, _last_scale (0.0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -90,6 +93,8 @@ AudioSource::AudioSource (Session& s, const XMLNode& node)
|
|||
, peak_leftover_cnt (0)
|
||||
, peak_leftover_size (0)
|
||||
, peak_leftovers (0)
|
||||
, _first_run (true)
|
||||
, _last_scale (0.0)
|
||||
{
|
||||
if (set_state (node, Stateful::loading_state_version)) {
|
||||
throw failed_constructor();
|
||||
|
@ -331,10 +336,13 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t
|
|||
PeakData::PeakDatum xmax;
|
||||
PeakData::PeakDatum xmin;
|
||||
int32_t to_read;
|
||||
ssize_t nread;
|
||||
framecnt_t zero_fill = 0;
|
||||
|
||||
ScopedFileDescriptor sfd (::open (peakpath.c_str(), O_RDONLY));
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
ScopedFileDescriptor sfd (::open (peakpath.c_str(), O_RDONLY | O_NONBLOCK));
|
||||
#else
|
||||
ScopedFileDescriptor sfd (::open (peakpath.c_str(), O_RDONLY | O_NOATIME | O_NONBLOCK));
|
||||
#endif
|
||||
|
||||
if (sfd < 0) {
|
||||
error << string_compose (_("Cannot open peakfile @ %1 for reading (%2)"), peakpath, strerror (errno)) << endmsg;
|
||||
|
@ -383,39 +391,44 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t
|
|||
}
|
||||
|
||||
if (scale == 1.0) {
|
||||
|
||||
off_t offset = 0;
|
||||
off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
|
||||
ssize_t bytes_to_read = sizeof (PeakData)* npeaks;
|
||||
size_t bytes_to_read = sizeof (PeakData)* npeaks;
|
||||
/* open, read, close */
|
||||
|
||||
DEBUG_TRACE (DEBUG::Peaks, "DIRECT PEAKS\n");
|
||||
|
||||
offset = lseek (sfd, first_peak_byte, SEEK_SET);
|
||||
uint32_t map_off = first_peak_byte;
|
||||
uint32_t read_map_off = map_off & ~(BUFSIZE - 1);
|
||||
uint32_t map_delta = map_off - read_map_off;
|
||||
size_t map_length = bytes_to_read + map_delta;
|
||||
|
||||
if (_first_run || (_last_map_off != map_off) || (_last_scale != samples_per_visual_peak) || (_last_raw_map_length < bytes_to_read)) {
|
||||
peak_cache.reset (new PeakData[npeaks]);
|
||||
boost::scoped_array<PeakData> staging (new PeakData[npeaks]);
|
||||
|
||||
char* addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
|
||||
if (addr == MAP_FAILED) {
|
||||
error << _("map failed - could not mmap peakfile.") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy ((void*)peak_cache.get(), (void*)(addr + map_delta), bytes_to_read);
|
||||
munmap (addr, map_length);
|
||||
|
||||
_last_map_off = map_off;
|
||||
_last_raw_map_length = bytes_to_read;
|
||||
_first_run = false;
|
||||
|
||||
if (zero_fill) {
|
||||
memset (&peak_cache[npeaks], 0, sizeof (PeakData) * zero_fill);
|
||||
}
|
||||
|
||||
if (offset != first_peak_byte) {
|
||||
error << string_compose(_("AudioSource: could not seek to correct location in peak file \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
nread = ::read (sfd, peaks, bytes_to_read);
|
||||
|
||||
if (nread != bytes_to_read) {
|
||||
DEBUG_TRACE (DEBUG::Peaks, string_compose ("[%1]: Cannot read peaks from peakfile! (read only %2 not %3 at sample %4 = byte %5 )\n"
|
||||
, _name, nread, npeaks, start, first_peak_byte));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (zero_fill) {
|
||||
memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
|
||||
}
|
||||
|
||||
_last_scale = samples_per_visual_peak;
|
||||
memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
framecnt_t tnp;
|
||||
|
||||
if (scale < 1.0) {
|
||||
|
||||
DEBUG_TRACE (DEBUG::Peaks, "DOWNSAMPLE\n");
|
||||
|
@ -430,88 +443,77 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t
|
|||
to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
|
||||
*/
|
||||
|
||||
const framecnt_t chunksize = (framecnt_t) min (expected_peaks, 65536.0);
|
||||
|
||||
boost::scoped_array<PeakData> staging(new PeakData[chunksize]);
|
||||
|
||||
/* compute the rounded up frame position */
|
||||
|
||||
framepos_t current_frame = start;
|
||||
framepos_t current_stored_peak = (framepos_t) ceil (current_frame / (double) samples_per_file_peak);
|
||||
framepos_t next_visual_peak = (framepos_t) ceil (current_frame / samples_per_visual_peak);
|
||||
framepos_t current_stored_peak = (framepos_t) ceil (start / (double) samples_per_file_peak);
|
||||
framepos_t next_visual_peak = (framepos_t) ceil (start / samples_per_visual_peak);
|
||||
double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
|
||||
framepos_t stored_peak_before_next_visual_peak = (framepos_t) next_visual_peak_frame / samples_per_file_peak;
|
||||
framecnt_t nvisual_peaks = 0;
|
||||
framecnt_t stored_peaks_read = 0;
|
||||
framecnt_t i = 0;
|
||||
uint32_t i = 0;
|
||||
framecnt_t chunksize = (framecnt_t) expected_peaks; // we read all the peaks we need in one hit.
|
||||
|
||||
/* handle the case where the initial visual peak is on a pixel boundary */
|
||||
|
||||
current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
|
||||
|
||||
/* open ... close during out: handling */
|
||||
|
||||
uint32_t map_off = (uint32_t) (ceil (start / (double) samples_per_file_peak)) * sizeof(PeakData);
|
||||
uint32_t read_map_off = map_off & ~(BUFSIZE - 1);
|
||||
uint32_t map_delta = map_off - read_map_off;
|
||||
size_t raw_map_length = chunksize * sizeof(PeakData);
|
||||
size_t map_length = (chunksize * sizeof(PeakData)) + map_delta;
|
||||
|
||||
while (nvisual_peaks < npeaks) {
|
||||
if (_first_run || (_last_map_off != map_off) || (_last_scale != samples_per_visual_peak) || (_last_raw_map_length < raw_map_length)) {
|
||||
peak_cache.reset (new PeakData[npeaks]);
|
||||
boost::scoped_array<PeakData> staging (new PeakData[chunksize]);
|
||||
|
||||
if (i == stored_peaks_read) {
|
||||
char* addr;
|
||||
addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
|
||||
if (addr == MAP_FAILED) {
|
||||
error << _("map failed - could not mmap peakfile.") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy ((void*)staging.get(), (void*)(addr + map_delta), raw_map_length);
|
||||
munmap (addr, map_length);
|
||||
|
||||
uint32_t start_byte = current_stored_peak * sizeof(PeakData);
|
||||
tnp = min ((framecnt_t)(_length/samples_per_file_peak - current_stored_peak), (framecnt_t) expected_peaks);
|
||||
to_read = min (chunksize, tnp);
|
||||
ssize_t bytes_to_read = sizeof (PeakData) * to_read;
|
||||
_last_map_off = map_off;
|
||||
_last_raw_map_length = raw_map_length;
|
||||
_first_run = false;
|
||||
_last_scale = samples_per_visual_peak;
|
||||
|
||||
while (nvisual_peaks < npeaks) {
|
||||
|
||||
DEBUG_TRACE (DEBUG::Peaks, string_compose ("reading %1 bytes from peakfile @ %2\n"
|
||||
, bytes_to_read, start_byte));
|
||||
xmax = -1.0;
|
||||
xmin = 1.0;
|
||||
|
||||
while ((current_stored_peak <= stored_peak_before_next_visual_peak) && (i < raw_map_length)) {
|
||||
|
||||
off_t offset = lseek (sfd, start_byte, SEEK_SET);
|
||||
|
||||
if (offset != start_byte) {
|
||||
error << string_compose(_("AudioSource: could not seek to correct location in peak file \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
xmax = max (xmax, staging[i].max);
|
||||
xmin = min (xmin, staging[i].min);
|
||||
++i;
|
||||
++current_stored_peak;
|
||||
}
|
||||
|
||||
if ((nread = ::read (sfd, staging.get(), bytes_to_read)) != bytes_to_read) {
|
||||
|
||||
off_t fend = lseek (sfd, 0, SEEK_END);
|
||||
|
||||
DEBUG_TRACE (DEBUG::Peaks, string_compose ("[%1]: cannot read peak data from peakfile (%2 peaks instead of %3) (%4) at start_byte = %5 _length = %6 versus len = %7 expected maxpeaks = %8 npeaks was %9"
|
||||
, _name, (nread / sizeof(PeakData)), to_read, g_strerror (errno), start_byte, _length, fend, ((_length - current_frame)/samples_per_file_peak), npeaks));
|
||||
return -1;
|
||||
}
|
||||
i = 0;
|
||||
stored_peaks_read = nread / sizeof(PeakData);
|
||||
peak_cache[nvisual_peaks].max = xmax;
|
||||
peak_cache[nvisual_peaks].min = xmin;
|
||||
++nvisual_peaks;
|
||||
next_visual_peak_frame = min ((double) start + cnt, (next_visual_peak_frame + samples_per_visual_peak));
|
||||
stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
|
||||
}
|
||||
|
||||
xmax = -1.0;
|
||||
xmin = 1.0;
|
||||
|
||||
while ((i < stored_peaks_read) && (current_stored_peak <= stored_peak_before_next_visual_peak)) {
|
||||
|
||||
xmax = max (xmax, staging[i].max);
|
||||
xmin = min (xmin, staging[i].min);
|
||||
++i;
|
||||
++current_stored_peak;
|
||||
--expected_peaks;
|
||||
if (zero_fill) {
|
||||
cerr << "Zero fill end of peaks (@ " << npeaks << " with " << zero_fill << endl;
|
||||
memset (&peak_cache[npeaks], 0, sizeof (PeakData) * zero_fill);
|
||||
}
|
||||
|
||||
peaks[nvisual_peaks].max = xmax;
|
||||
peaks[nvisual_peaks].min = xmin;
|
||||
++nvisual_peaks;
|
||||
++next_visual_peak;
|
||||
|
||||
//next_visual_peak_frame = min ((next_visual_peak * samples_per_visual_peak), (next_visual_peak_frame+samples_per_visual_peak) );
|
||||
next_visual_peak_frame = min ((double) start+cnt, (next_visual_peak_frame+samples_per_visual_peak) );
|
||||
stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
|
||||
}
|
||||
|
||||
if (zero_fill) {
|
||||
cerr << "Zero fill end of peaks (@ " << npeaks << " with " << zero_fill << endl;
|
||||
memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
|
||||
}
|
||||
memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData));
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
|
||||
DEBUG_TRACE (DEBUG::Peaks, "UPSAMPLE\n");
|
||||
|
||||
/* the caller wants
|
||||
|
@ -683,7 +685,7 @@ AudioSource::done_with_peakfile_writes (bool done)
|
|||
_peaks_built = true;
|
||||
PeaksReady (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
|
||||
close (_peakfile_fd);
|
||||
_peakfile_fd = -1;
|
||||
}
|
||||
|
|
|
@ -232,8 +232,8 @@ Curve::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
|||
for (Points::const_iterator p = _points.begin(); p != _points.end(); ++p) {
|
||||
Duple window_space (item_to_window (*p));
|
||||
context->arc (window_space.x, window_space.y, 5.0, 0.0, 2 * M_PI);
|
||||
context->stroke ();
|
||||
}
|
||||
context->stroke ();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -384,6 +384,10 @@ WaveView::draw_image (Cairo::RefPtr<Cairo::ImageSurface>& image, PeakData* _peak
|
|||
Cairo::RefPtr<Cairo::Context> outline_context = Cairo::Context::create (images.outline);
|
||||
Cairo::RefPtr<Cairo::Context> clip_context = Cairo::Context::create (images.clip);
|
||||
Cairo::RefPtr<Cairo::Context> zero_context = Cairo::Context::create (images.zero);
|
||||
wave_context->set_antialias (Cairo::ANTIALIAS_NONE);
|
||||
outline_context->set_antialias (Cairo::ANTIALIAS_NONE);
|
||||
clip_context->set_antialias (Cairo::ANTIALIAS_NONE);
|
||||
zero_context->set_antialias (Cairo::ANTIALIAS_NONE);
|
||||
|
||||
boost::scoped_array<LineTips> tips (new LineTips[n_peaks]);
|
||||
|
||||
|
@ -414,16 +418,17 @@ WaveView::draw_image (Cairo::RefPtr<Cairo::ImageSurface>& image, PeakData* _peak
|
|||
tips[i].top = y_extent (p, false);
|
||||
tips[i].spread = p * (_height - 1.0);
|
||||
|
||||
if (fabs (_peaks[i].max) >= clip_level) {
|
||||
if (_peaks[i].max >= clip_level) {
|
||||
tips[i].clip_max = true;
|
||||
}
|
||||
|
||||
if (fabs (_peaks[i].min) >= clip_level) {
|
||||
if (-(_peaks[i].min) >= clip_level) {
|
||||
tips[i].clip_min = true;
|
||||
}
|
||||
}
|
||||
|
||||
} else {for (int i = 0; i < n_peaks; ++i) {
|
||||
} else {
|
||||
for (int i = 0; i < n_peaks; ++i) {
|
||||
|
||||
tips[i].bot = height() - 1.0;
|
||||
const double p = max(fabs (_peaks[i].max), fabs (_peaks[i].min));
|
||||
|
@ -443,22 +448,11 @@ WaveView::draw_image (Cairo::RefPtr<Cairo::ImageSurface>& image, PeakData* _peak
|
|||
double top = _peaks[i].max;
|
||||
double bot = _peaks[i].min;
|
||||
|
||||
if (_peaks[i].max > 0 && _peaks[i].min > 0) {
|
||||
if (fabs (_peaks[i].max) >= clip_level) {
|
||||
if (_peaks[i].max >= clip_level) {
|
||||
tips[i].clip_max = true;
|
||||
}
|
||||
}
|
||||
else if (_peaks[i].max < 0 && _peaks[i].min < 0) {
|
||||
if (fabs (_peaks[i].min) >= clip_level) {
|
||||
tips[i].clip_min = true;
|
||||
}
|
||||
} else {
|
||||
if (fabs (_peaks[i].max) >= clip_level) {
|
||||
tips[i].clip_max = true;
|
||||
}
|
||||
if (fabs (_peaks[i].min) >= clip_level) {
|
||||
tips[i].clip_min = true;
|
||||
}
|
||||
if (-(_peaks[i].min) >= clip_level) {
|
||||
tips[i].clip_min = true;
|
||||
}
|
||||
|
||||
if (top > 0.0) {
|
||||
|
@ -479,32 +473,21 @@ WaveView::draw_image (Cairo::RefPtr<Cairo::ImageSurface>& image, PeakData* _peak
|
|||
|
||||
tips[i].top = y_extent (top, false);
|
||||
tips[i].bot = y_extent (bot, true);
|
||||
tips[i].spread = fabs (tips[i].top - tips[i].bot);
|
||||
tips[i].spread = tips[i].bot - tips[i].top;
|
||||
}
|
||||
|
||||
} else {
|
||||
for (int i = 0; i < n_peaks; ++i) {
|
||||
if (_peaks[i].max > 0 && _peaks[i].min > 0) {
|
||||
if (fabs (_peaks[i].max) >= clip_level) {
|
||||
tips[i].clip_max = true;
|
||||
}
|
||||
if (_peaks[i].max >= clip_level) {
|
||||
tips[i].clip_max = true;
|
||||
}
|
||||
else if (_peaks[i].max < 0 && _peaks[i].min < 0) {
|
||||
if (fabs (_peaks[i].min) >= clip_level) {
|
||||
tips[i].clip_min = true;
|
||||
}
|
||||
} else {
|
||||
if (fabs (_peaks[i].max) >= clip_level) {
|
||||
tips[i].clip_max = true;
|
||||
}
|
||||
if (fabs (_peaks[i].min) >= clip_level) {
|
||||
tips[i].clip_min = true;
|
||||
}
|
||||
if (-(_peaks[i].min) >= clip_level) {
|
||||
tips[i].clip_min = true;
|
||||
}
|
||||
|
||||
tips[i].top = y_extent (_peaks[i].max, false);
|
||||
tips[i].bot = y_extent (_peaks[i].min, true);
|
||||
tips[i].spread = fabs (tips[i].top - tips[i].bot);
|
||||
tips[i].spread = tips[i].bot - tips[i].top;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -521,7 +504,6 @@ WaveView::draw_image (Cairo::RefPtr<Cairo::ImageSurface>& image, PeakData* _peak
|
|||
wave_context->set_line_width (1.0);
|
||||
wave_context->translate (0.5, +0.5);
|
||||
|
||||
outline_context->set_line_cap (Cairo::LINE_CAP_ROUND);
|
||||
outline_context->set_line_width (1.0);
|
||||
outline_context->translate (0.5, +0.5);
|
||||
|
||||
|
@ -536,6 +518,7 @@ WaveView::draw_image (Cairo::RefPtr<Cairo::ImageSurface>& image, PeakData* _peak
|
|||
*/
|
||||
|
||||
const double clip_height = min (7.0, ceil (_height * 0.05));
|
||||
bool draw_outline_as_wave = false;
|
||||
|
||||
/* There are 3 possible components to draw at each x-axis position: the
|
||||
waveform "line", the zero line and an outline/clip indicator. We
|
||||
|
@ -594,19 +577,23 @@ WaveView::draw_image (Cairo::RefPtr<Cairo::ImageSurface>& image, PeakData* _peak
|
|||
for (int i = 0; i < n_peaks; ++i) {
|
||||
|
||||
/* waveform line */
|
||||
|
||||
|
||||
if (tips[i].spread >= 2.0) {
|
||||
wave_context->move_to (i, tips[i].top);
|
||||
wave_context->line_to (i, tips[i].bot);
|
||||
}
|
||||
/* draw square waves and other discontiguous points clearly */
|
||||
if (i > 0) {
|
||||
if (tips[i-1].top + 2 < tips[i].bot) {
|
||||
if (tips[i-1].top + 2 < tips[i].top) {
|
||||
wave_context->move_to (i-1, tips[i-1].top);
|
||||
wave_context->line_to (i, tips[i].bot);
|
||||
}
|
||||
else if (tips[i-1].bot > tips[i].top + 2) {
|
||||
wave_context->move_to (i-1, tips[i-1].bot);
|
||||
wave_context->line_to (i-1, (tips[i].bot + tips[i-1].top)/2);
|
||||
wave_context->move_to (i, (tips[i].bot + tips[i-1].top)/2);
|
||||
wave_context->line_to (i, tips[i].top);
|
||||
} else if (tips[i-1].bot > tips[i].bot + 2) {
|
||||
wave_context->move_to (i-1, tips[i-1].bot);
|
||||
wave_context->line_to (i-1, (tips[i].top + tips[i-1].bot)/2);
|
||||
wave_context->move_to (i, (tips[i].top + tips[i-1].bot)/2);
|
||||
wave_context->line_to (i, tips[i].bot);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -618,6 +605,7 @@ WaveView::draw_image (Cairo::RefPtr<Cairo::ImageSurface>& image, PeakData* _peak
|
|||
}
|
||||
|
||||
if (tips[i].spread > 1.0) {
|
||||
draw_outline_as_wave = false;
|
||||
/* lower outline/clip indicator */
|
||||
if (_global_show_waveform_clipping && tips[i].clip_min) {
|
||||
clip_context->move_to (i, tips[i].bot);
|
||||
|
@ -625,11 +613,12 @@ WaveView::draw_image (Cairo::RefPtr<Cairo::ImageSurface>& image, PeakData* _peak
|
|||
const double sign = tips[i].bot > height_2 ? -1 : 1;
|
||||
clip_context->rel_line_to (0, sign * min (clip_height, ceil (tips[i].spread + .5)));
|
||||
} else {
|
||||
outline_context->move_to (i, tips[i].bot);
|
||||
outline_context->move_to (i, tips[i].bot + 0.5);
|
||||
/* normal lower terminal dot */
|
||||
outline_context->close_path ();
|
||||
outline_context->rel_line_to (0, -0.5);
|
||||
}
|
||||
} else {
|
||||
draw_outline_as_wave = true;
|
||||
if (tips[i].clip_min) {
|
||||
// make sure we draw the clip
|
||||
tips[i].clip_max = true;
|
||||
|
@ -643,9 +632,17 @@ WaveView::draw_image (Cairo::RefPtr<Cairo::ImageSurface>& image, PeakData* _peak
|
|||
const double sign = tips[i].top > height_2 ? -1 : 1;
|
||||
clip_context->rel_line_to (0, sign * min(clip_height, ceil(tips[i].spread + .5)));
|
||||
} else {
|
||||
outline_context->move_to (i, tips[i].top);
|
||||
/* normal upper terminal dot */
|
||||
outline_context->close_path ();
|
||||
if (draw_outline_as_wave) {
|
||||
wave_context->move_to (i, tips[i].top + 0.5);
|
||||
/* special case where outline only is drawn.
|
||||
is this correct? too short by 0.5?
|
||||
*/
|
||||
wave_context->rel_line_to (0, -0.5);
|
||||
} else {
|
||||
outline_context->move_to (i, tips[i].top + 0.5);
|
||||
/* normal upper terminal dot */
|
||||
outline_context->rel_line_to (0, -0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -757,8 +754,8 @@ WaveView::get_image (Cairo::RefPtr<Cairo::ImageSurface>& image, framepos_t start
|
|||
/* we can request data from anywhere in the Source, between 0 and its length
|
||||
*/
|
||||
|
||||
framepos_t sample_start = max ((framepos_t) 0, (center - canvas_samples));
|
||||
framepos_t sample_end = min (center + canvas_samples, _region->source_length (0));
|
||||
framepos_t sample_start = max ((framepos_t) _region->start(), (center - canvas_samples));
|
||||
framepos_t sample_end = min (center + canvas_samples, _region->start() + _region->length());
|
||||
|
||||
const int n_peaks = llrintf ((sample_end - sample_start)/ (double) _samples_per_pixel);
|
||||
|
||||
|
|
|
@ -241,13 +241,6 @@ XFadeCurve::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) co
|
|||
|
||||
#define IS (_xfadeposition == Start)
|
||||
|
||||
/* fill primary fade */
|
||||
context->begin_new_path ();
|
||||
context->append_path (IS ? *path_in : *path_out);
|
||||
close_path(draw, context, IS ?_in : _out, false);
|
||||
set_source_rgba (context, _fill_color);
|
||||
context->fill ();
|
||||
|
||||
/* fill background fade */
|
||||
context->save ();
|
||||
context->begin_new_path ();
|
||||
|
@ -263,6 +256,13 @@ XFadeCurve::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) co
|
|||
context->fill ();
|
||||
context->restore ();
|
||||
|
||||
/* fill primary fade */
|
||||
context->begin_new_path ();
|
||||
context->append_path (IS ? *path_in : *path_out);
|
||||
close_path(draw, context, IS ?_in : _out, false);
|
||||
set_source_rgba (context, _fill_color);
|
||||
context->fill ();
|
||||
|
||||
/* draw lines over fills */
|
||||
set_source_rgba (context, IS ? _outline_color : outline_shaded);
|
||||
context->set_line_width (IS ? 1.0 : .5);
|
||||
|
|
Loading…
Reference in New Issue