ardour
audiosource.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2000 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #ifdef COMPILER_MSVC
21 #include <sys/utime.h>
22 #else
23 #include <unistd.h>
24 #include <utime.h>
25 #endif
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <float.h>
29 #include <cerrno>
30 #include <ctime>
31 #include <cmath>
32 #include <iomanip>
33 #include <fstream>
34 #include <algorithm>
35 #include <vector>
36 
37 #ifdef PLATFORM_WINDOWS
38 #include <windows.h>
39 
40 #else
41 #include <sys/mman.h>
42 
43 #endif
44 
45 #include <glib.h>
46 #include <glib/gstdio.h>
47 
48 #include <boost/scoped_ptr.hpp>
49 
50 #include <glibmm/fileutils.h>
51 #include <glibmm/miscutils.h>
52 
54 #include "pbd/xml++.h"
55 
56 #include "ardour/audiosource.h"
59 
60 #include "i18n.h"
61 
62 #include "ardour/debug.h"
63 
64 using namespace std;
65 using namespace ARDOUR;
66 using namespace PBD;
67 
68 Glib::Threads::Mutex AudioSource::_level_buffer_lock;
69 vector<boost::shared_array<Sample> > AudioSource::_mixdown_buffers;
70 vector<boost::shared_array<gain_t> > AudioSource::_gain_buffers;
71 size_t AudioSource::_working_buffers_size = 0;
72 bool AudioSource::_build_missing_peakfiles = false;
73 
75 bool AudioSource::_build_peakfiles = false;
76 
77 #define _FPP 256
78 
79 AudioSource::AudioSource (Session& s, string name)
80  : Source (s, DataType::AUDIO, name)
81  , _length (0)
82  , _peak_byte_max (0)
83  , _peaks_built (false)
84  , _peakfile_fd (-1)
85  , peak_leftover_cnt (0)
86  , peak_leftover_size (0)
87  , peak_leftovers (0)
88  , _first_run (true)
89  , _last_scale (0.0)
90  , _last_map_off (0)
91  , _last_raw_map_length (0)
92 {
93 }
94 
95 AudioSource::AudioSource (Session& s, const XMLNode& node)
96  : Source (s, node)
97  , _length (0)
98  , _peak_byte_max (0)
99  , _peaks_built (false)
100  , _peakfile_fd (-1)
101  , peak_leftover_cnt (0)
102  , peak_leftover_size (0)
103  , peak_leftovers (0)
104  , _first_run (true)
105  , _last_scale (0.0)
106  , _last_map_off (0)
107  , _last_raw_map_length (0)
108 {
110  throw failed_constructor();
111  }
112 }
113 
115 {
116  /* shouldn't happen but make sure we don't leak file descriptors anyway */
117 
118  if (peak_leftover_cnt) {
119  cerr << "AudioSource destroyed with leftover peak data pending" << endl;
120  }
121 
122  if ((-1) != _peakfile_fd) {
123  close (_peakfile_fd);
124  _peakfile_fd = -1;
125  }
126 
127  delete [] peak_leftovers;
128 }
129 
130 XMLNode&
132 {
133  XMLNode& node (Source::get_state());
134 
135  if (_captured_for.length()) {
136  node.add_property ("captured-for", _captured_for);
137  }
138 
139  return node;
140 }
141 
142 int
143 AudioSource::set_state (const XMLNode& node, int /*version*/)
144 {
145  const XMLProperty* prop;
146 
147  if ((prop = node.property ("captured-for")) != 0) {
148  _captured_for = prop->value();
149  }
150 
151  return 0;
152 }
153 
154 bool
156 {
157  return _length == 0;
158 }
159 
162 {
163  return _length;
164 }
165 
166 void
168 {
169  if (len > _length) {
170  _length = len;
171  }
172 }
173 
174 
175 /***********************************************************************
176  PEAK FILE STUFF
177  ***********************************************************************/
178 
188 bool
189 AudioSource::peaks_ready (boost::function<void()> doThisWhenReady, ScopedConnection** connect_here_if_not, EventLoop* event_loop) const
190 {
191  bool ret;
193 
194  if (!(ret = _peaks_built)) {
195  *connect_here_if_not = new ScopedConnection;
196  PeaksReady.connect (**connect_here_if_not, MISSING_INVALIDATOR, doThisWhenReady, event_loop);
197  }
198 
199  return ret;
200 }
201 
202 void
204 {
205  GStatBuf statbuf;
206 
207  if (g_stat (peakpath.c_str(), &statbuf) != 0 || statbuf.st_size == 0) {
208  return;
209  }
210 
211  struct utimbuf tbuf;
212 
213  tbuf.actime = statbuf.st_atime;
214  tbuf.modtime = time ((time_t*) 0);
215 
216  g_utime (peakpath.c_str(), &tbuf);
217 }
218 
219 int
221 {
222  /* caller must hold _lock */
223 
224  string oldpath = peakpath;
225 
226  if (Glib::file_test (oldpath, Glib::FILE_TEST_EXISTS)) {
227  if (g_rename (oldpath.c_str(), newpath.c_str()) != 0) {
228  error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
229  return -1;
230  }
231  }
232 
233  peakpath = newpath;
234 
235  return 0;
236 }
237 
238 int
240 {
241  GStatBuf statbuf;
242 
243  peakpath = peak_path (audio_path);
244 
245  DEBUG_TRACE(DEBUG::Peaks, string_compose ("Initialize Peakfile %1 for Audio file %2\n", peakpath, audio_path));
246 
247  /* if the peak file should be there, but isn't .... */
248 
249  if (!empty() && !Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
250  peakpath = find_broken_peakfile (peakpath, audio_path);
251  }
252 
253  if (g_stat (peakpath.c_str(), &statbuf)) {
254  if (errno != ENOENT) {
255  /* it exists in the peaks dir, but there is some kind of error */
256 
257  error << string_compose(_("AudioSource: cannot stat peakfile \"%1\""), peakpath) << endmsg;
258  return -1;
259  }
260 
261  DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 does not exist\n", peakpath));
262 
263  _peaks_built = false;
264 
265  } else {
266 
267  /* we found it in the peaks dir, so check it out */
268 
269  if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_timeline_position) / _FPP) * sizeof (PeakData)))) {
270  DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 is empty\n", peakpath));
271  _peaks_built = false;
272  } else {
273  // Check if the audio file has changed since the peakfile was built.
274  struct stat stat_file;
275  int err = stat (audio_path.c_str(), &stat_file);
276 
277  if (err) {
278 
279  /* no audio path - nested source or we can't
280  read it or ... whatever, use the peakfile as-is.
281  */
282  DEBUG_TRACE(DEBUG::Peaks, string_compose("Error when calling stat on Peakfile %1\n", peakpath));
283 
284  _peaks_built = true;
285  _peak_byte_max = statbuf.st_size;
286 
287  } else {
288 
289  /* allow 6 seconds slop on checking peak vs. file times because of various
290  disk action "races"
291  */
292 
293  if (stat_file.st_mtime > statbuf.st_mtime && (stat_file.st_mtime - statbuf.st_mtime > 6)) {
294  _peaks_built = false;
295  _peak_byte_max = 0;
296  } else {
297  _peaks_built = true;
298  _peak_byte_max = statbuf.st_size;
299  }
300  }
301  }
302  }
303 
306  }
307 
308  return 0;
309 }
310 
312 AudioSource::read (Sample *dst, framepos_t start, framecnt_t cnt, int /*channel*/) const
313 {
314  assert (cnt >= 0);
315 
317  return read_unlocked (dst, start, cnt);
318 }
319 
322 {
324  /* any write makes the file not removable */
325  _flags = Flag (_flags & ~Removable);
326  return write_unlocked (dst, cnt);
327 }
328 
329 int
330 AudioSource::read_peaks (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt, double samples_per_visual_peak) const
331 {
332  return read_peaks_with_fpp (peaks, npeaks, start, cnt, samples_per_visual_peak, _FPP);
333 }
334 
339 int
341  double samples_per_visual_peak, framecnt_t samples_per_file_peak) const
342 {
344  double scale;
345  double expected_peaks;
346  PeakData::PeakDatum xmax;
347  PeakData::PeakDatum xmin;
348  int32_t to_read;
349 #ifdef PLATFORM_WINDOWS
350  SYSTEM_INFO system_info;
351  GetSystemInfo (&system_info);
352  const int bufsize = system_info.dwAllocationGranularity;;
353 #else
354  const int bufsize = sysconf(_SC_PAGESIZE);
355 #endif
356  framecnt_t read_npeaks = npeaks;
357  framecnt_t zero_fill = 0;
358 
359  ScopedFileDescriptor sfd (::open (peakpath.c_str(), O_RDONLY));
360 
361  if (sfd < 0) {
362  error << string_compose (_("Cannot open peakfile @ %1 for reading (%2)"), peakpath, strerror (errno)) << endmsg;
363  return -1;
364  }
365 
366  expected_peaks = (cnt / (double) samples_per_file_peak);
367  scale = npeaks/expected_peaks;
368 
369  DEBUG_TRACE (DEBUG::Peaks, string_compose (" ======>RP: npeaks = %1 start = %2 cnt = %3 len = %4 samples_per_visual_peak = %5 expected was %6 ... scale = %7 PD ptr = %8\n"
370  , npeaks, start, cnt, _length, samples_per_visual_peak, expected_peaks, scale, peaks));
371 
372  /* fix for near-end-of-file conditions */
373 
374  if (cnt > _length - start) {
375  // cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << " (" << _length - start << ")" << endl;
376  cnt = _length - start;
377  read_npeaks = min ((framecnt_t) floor (cnt / samples_per_visual_peak), npeaks);
378  zero_fill = npeaks - read_npeaks;
379  }
380 
381  // cerr << "actual npeaks = " << read_npeaks << " zf = " << zero_fill << endl;
382 
383  if (npeaks == cnt) {
384 
385  DEBUG_TRACE (DEBUG::Peaks, "RAW DATA\n");
386 
387  /* no scaling at all, just get the sample data and duplicate it for
388  both max and min peak values.
389  */
390 
391  boost::scoped_array<Sample> raw_staging(new Sample[cnt]);
392 
393  if (read_unlocked (raw_staging.get(), start, cnt) != cnt) {
394  error << _("cannot read sample data for unscaled peak computation") << endmsg;
395  return -1;
396  }
397 
398  for (framecnt_t i = 0; i < npeaks; ++i) {
399  peaks[i].max = raw_staging[i];
400  peaks[i].min = raw_staging[i];
401  }
402 
403  return 0;
404  }
405 
406  if (scale == 1.0) {
407  off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
408  size_t bytes_to_read = sizeof (PeakData) * read_npeaks;
409  /* open, read, close */
410 
411  DEBUG_TRACE (DEBUG::Peaks, "DIRECT PEAKS\n");
412 
413  off_t map_off = first_peak_byte;
414  off_t read_map_off = map_off & ~(bufsize - 1);
415  off_t map_delta = map_off - read_map_off;
416  size_t map_length = bytes_to_read + map_delta;
417 
418  if (_first_run || (_last_scale != samples_per_visual_peak) || (_last_map_off != map_off) || (_last_raw_map_length < bytes_to_read)) {
419  peak_cache.reset (new PeakData[npeaks]);
420  char* addr;
421 #ifdef PLATFORM_WINDOWS
422  HANDLE file_handle = (HANDLE) _get_osfhandle(int(sfd));
423  HANDLE map_handle;
424  LPVOID view_handle;
425  bool err_flag;
426 
427  map_handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL);
428  if (map_handle == NULL) {
429  error << string_compose (_("map failed - could not create file mapping for peakfile %1."), peakpath) << endmsg;
430  return -1;
431  }
432 
433  view_handle = MapViewOfFile(map_handle, FILE_MAP_READ, 0, read_map_off, map_length);
434  if (view_handle == NULL) {
435  error << string_compose (_("map failed - could not map peakfile %1."), peakpath) << endmsg;
436  return -1;
437  }
438 
439  addr = (char*) view_handle;
440 
441  memcpy ((void*)peak_cache.get(), (void*)(addr + map_delta), bytes_to_read);
442 
443  err_flag = UnmapViewOfFile (view_handle);
444  err_flag = CloseHandle(map_handle);
445  if(!err_flag) {
446  error << string_compose (_("unmap failed - could not unmap peakfile %1."), peakpath) << endmsg;
447  return -1;
448  }
449 #else
450  addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
451  if (addr == MAP_FAILED) {
452  error << string_compose (_("map failed - could not mmap peakfile %1."), peakpath) << endmsg;
453  return -1;
454  }
455 
456  memcpy ((void*)peak_cache.get(), (void*)(addr + map_delta), bytes_to_read);
457  munmap (addr, map_length);
458 #endif
459  if (zero_fill) {
460  memset (&peak_cache[read_npeaks], 0, sizeof (PeakData) * zero_fill);
461  }
462 
463  _first_run = false;
464  _last_scale = samples_per_visual_peak;
465  _last_map_off = map_off;
466  _last_raw_map_length = bytes_to_read;
467  }
468 
469  memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData));
470 
471  return 0;
472  }
473 
474  if (scale < 1.0) {
475 
476  DEBUG_TRACE (DEBUG::Peaks, "DOWNSAMPLE\n");
477 
478  /* the caller wants:
479 
480  - more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
481  - less peaks than the peakfile holds for the same range
482 
483  So, read a block into a staging area, and then downsample from there.
484 
485  to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
486  */
487 
488  const framecnt_t chunksize = (framecnt_t) expected_peaks; // we read all the peaks we need in one hit.
489 
490  /* compute the rounded up frame position */
491 
492  framepos_t current_stored_peak = (framepos_t) ceil (start / (double) samples_per_file_peak);
493  framepos_t next_visual_peak = (framepos_t) ceil (start / samples_per_visual_peak);
494  double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
495  framepos_t stored_peak_before_next_visual_peak = (framepos_t) next_visual_peak_frame / samples_per_file_peak;
496  framecnt_t nvisual_peaks = 0;
497  uint32_t i = 0;
498 
499  /* handle the case where the initial visual peak is on a pixel boundary */
500 
501  current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
502 
503  /* open ... close during out: handling */
504 
505  off_t map_off = (uint32_t) (ceil (start / (double) samples_per_file_peak)) * sizeof(PeakData);
506  off_t read_map_off = map_off & ~(bufsize - 1);
507  off_t map_delta = map_off - read_map_off;
508  size_t raw_map_length = chunksize * sizeof(PeakData);
509  size_t map_length = (chunksize * sizeof(PeakData)) + map_delta;
510 
511  if (_first_run || (_last_scale != samples_per_visual_peak) || (_last_map_off != map_off) || (_last_raw_map_length < raw_map_length)) {
512  peak_cache.reset (new PeakData[npeaks]);
513  boost::scoped_array<PeakData> staging (new PeakData[chunksize]);
514 
515  char* addr;
516 #ifdef PLATFORM_WINDOWS
517  HANDLE file_handle = (HANDLE) _get_osfhandle(int(sfd));
518  HANDLE map_handle;
519  LPVOID view_handle;
520  bool err_flag;
521 
522  map_handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL);
523  if (map_handle == NULL) {
524  error << string_compose (_("map failed - could not create file mapping for peakfile %1."), peakpath) << endmsg;
525  return -1;
526  }
527 
528  view_handle = MapViewOfFile(map_handle, FILE_MAP_READ, 0, read_map_off, map_length);
529  if (view_handle == NULL) {
530  error << string_compose (_("map failed - could not map peakfile %1."), peakpath) << endmsg;
531  return -1;
532  }
533 
534  addr = (char *) view_handle;
535 
536  memcpy ((void*)staging.get(), (void*)(addr + map_delta), raw_map_length);
537 
538  err_flag = UnmapViewOfFile (view_handle);
539  err_flag = CloseHandle(map_handle);
540  if(!err_flag) {
541  error << string_compose (_("unmap failed - could not unmap peakfile %1."), peakpath) << endmsg;
542  return -1;
543  }
544 #else
545  addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
546  if (addr == MAP_FAILED) {
547  error << string_compose (_("map failed - could not mmap peakfile %1."), peakpath) << endmsg;
548  return -1;
549  }
550 
551  memcpy ((void*)staging.get(), (void*)(addr + map_delta), raw_map_length);
552  munmap (addr, map_length);
553 #endif
554  while (nvisual_peaks < read_npeaks) {
555 
556  xmax = -1.0;
557  xmin = 1.0;
558 
559  while ((current_stored_peak <= stored_peak_before_next_visual_peak) && (i < chunksize)) {
560 
561  xmax = max (xmax, staging[i].max);
562  xmin = min (xmin, staging[i].min);
563  ++i;
564  ++current_stored_peak;
565  }
566 
567  peak_cache[nvisual_peaks].max = xmax;
568  peak_cache[nvisual_peaks].min = xmin;
569  ++nvisual_peaks;
570  next_visual_peak_frame = min ((double) start + cnt, (next_visual_peak_frame + samples_per_visual_peak));
571  stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
572  }
573 
574  if (zero_fill) {
575  cerr << "Zero fill end of peaks (@ " << read_npeaks << " with " << zero_fill << ")" << endl;
576  memset (&peak_cache[read_npeaks], 0, sizeof (PeakData) * zero_fill);
577  }
578 
579  _first_run = false;
580  _last_scale = samples_per_visual_peak;
581  _last_map_off = map_off;
582  _last_raw_map_length = raw_map_length;
583  }
584 
585  memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData));
586 
587  } else {
588  DEBUG_TRACE (DEBUG::Peaks, "UPSAMPLE\n");
589 
590  /* the caller wants
591 
592  - less frames-per-peak (more resolution)
593  - more peaks than stored in the Peakfile
594 
595  So, fetch data from the raw source, and generate peak
596  data on the fly.
597  */
598 
599  framecnt_t frames_read = 0;
600  framepos_t current_frame = start;
601  framecnt_t i = 0;
602  framecnt_t nvisual_peaks = 0;
603  framecnt_t chunksize = (framecnt_t) min (cnt, (framecnt_t) 4096);
604  boost::scoped_array<Sample> raw_staging(new Sample[chunksize]);
605 
606  framepos_t frame_pos = start;
607  double pixel_pos = floor (frame_pos / samples_per_visual_peak);
608  double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
609  double pixels_per_frame = 1.0 / samples_per_visual_peak;
610 
611  xmin = 1.0;
612  xmax = -1.0;
613 
614  while (nvisual_peaks < read_npeaks) {
615 
616  if (i == frames_read) {
617 
618  to_read = min (chunksize, (framecnt_t)(_length - current_frame));
619 
620  if (current_frame >= _length) {
621 
622  /* hmm, error condition - we've reached the end of the file
623  without generating all the peak data. cook up a zero-filled
624  data buffer and then use it. this is simpler than
625  adjusting zero_fill and read_npeaks and then breaking out of
626  this loop early
627  */
628 
629  memset (raw_staging.get(), 0, sizeof (Sample) * chunksize);
630 
631  } else {
632 
633  to_read = min (chunksize, (_length - current_frame));
634 
635 
636  if ((frames_read = read_unlocked (raw_staging.get(), current_frame, to_read)) == 0) {
637  error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
638  _name, to_read, current_frame, _length, strerror (errno))
639  << endmsg;
640  return -1;
641  }
642  }
643 
644  i = 0;
645  }
646 
647  xmax = max (xmax, raw_staging[i]);
648  xmin = min (xmin, raw_staging[i]);
649  ++i;
650  ++current_frame;
651  pixel_pos += pixels_per_frame;
652 
653  if (pixel_pos >= next_pixel_pos) {
654 
655  peaks[nvisual_peaks].max = xmax;
656  peaks[nvisual_peaks].min = xmin;
657  ++nvisual_peaks;
658  xmin = 1.0;
659  xmax = -1.0;
660 
661  next_pixel_pos = ceil (pixel_pos + 0.5);
662  }
663  }
664 
665  if (zero_fill) {
666  memset (&peaks[read_npeaks], 0, sizeof (PeakData) * zero_fill);
667  }
668  }
669 
670  DEBUG_TRACE (DEBUG::Peaks, "READPEAKS DONE\n");
671  return 0;
672 }
673 
674 int
676 {
677  const framecnt_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
678 
679  DEBUG_TRACE (DEBUG::Peaks, "Building peaks from scratch\n");
680 
681  int ret = -1;
682 
683  {
684  /* hold lock while building peaks */
685 
687 
689  goto out;
690  }
691 
692  framecnt_t current_frame = 0;
693  framecnt_t cnt = _length;
694 
695  _peaks_built = false;
696  boost::scoped_array<Sample> buf(new Sample[bufsize]);
697 
698  while (cnt) {
699 
700  framecnt_t frames_to_read = min (bufsize, cnt);
701  framecnt_t frames_read;
702 
703  if ((frames_read = read_unlocked (buf.get(), current_frame, frames_to_read)) != frames_to_read) {
704  error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
706  goto out;
707  }
708 
709  if (compute_and_write_peaks (buf.get(), current_frame, frames_read, true, false, _FPP)) {
710  break;
711  }
712 
713  current_frame += frames_read;
714  cnt -= frames_read;
715  }
716 
717  if (cnt == 0) {
718  /* success */
720  }
721 
722  done_with_peakfile_writes ((cnt == 0));
723  if (cnt == 0) {
724  ret = 0;
725  }
726  }
727 
728  out:
729  if (ret) {
730  DEBUG_TRACE (DEBUG::Peaks, string_compose("Could not write peak data, attempting to remove peakfile %1\n", peakpath));
731  ::g_unlink (peakpath.c_str());
732  }
733 
734  return ret;
735 }
736 
737 int
739 {
740  if ((_peakfile_fd = open (peakpath.c_str(), O_CREAT|O_RDWR, 0664)) < 0) {
741  error << string_compose(_("AudioSource: cannot open peakpath (c) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
742  return -1;
743  }
744  return 0;
745 }
746 
747 void
749 {
750  if (peak_leftover_cnt) {
751  compute_and_write_peaks (0, 0, 0, true, false, _FPP);
752  }
753 
754  if (done) {
756  _peaks_built = true;
757  PeaksReady (); /* EMIT SIGNAL */
758  }
759 
760  close (_peakfile_fd);
761  _peakfile_fd = -1;
762 }
763 
765 int
767  bool force, bool intermediate_peaks_ready)
768 {
769  return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
770 }
771 
772 int
774  bool force, bool intermediate_peaks_ready, framecnt_t fpp)
775 {
776  framecnt_t to_do;
777  uint32_t peaks_computed;
778  framepos_t current_frame;
779  framecnt_t frames_done;
780  const size_t blocksize = (128 * 1024);
781  off_t first_peak_byte;
782  boost::scoped_array<Sample> buf2;
783 
784  if (_peakfile_fd < 0) {
786  return -1;
787  }
788  }
789 
790  restart:
791  if (peak_leftover_cnt) {
792 
793  if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
794 
795  /* uh-oh, ::seek() since the last ::compute_and_write_peaks(),
796  and we have leftovers. flush a single peak (since the leftovers
797  never represent more than that, and restart.
798  */
799 
800  PeakData x;
801 
802  x.min = peak_leftovers[0];
803  x.max = peak_leftovers[0];
804 
805  off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
806 
807  off_t offset = lseek (_peakfile_fd, byte, SEEK_SET);
808 
809  if (offset != byte) {
810  error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
811  return -1;
812  }
813 
814  if (::write (_peakfile_fd, &x, sizeof (PeakData)) != sizeof (PeakData)) {
815  error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
816  return -1;
817  }
818 
819  _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
820 
821  {
824  if (intermediate_peaks_ready) {
825  PeaksReady (); /* EMIT SIGNAL */
826  }
827  }
828 
829  /* left overs are done */
830 
831  peak_leftover_cnt = 0;
832  goto restart;
833  }
834 
835  /* else ... had leftovers, but they immediately preceed the new data, so just
836  merge them and compute.
837  */
838 
839  /* make a new contiguous buffer containing leftovers and the new stuff */
840 
841  to_do = cnt + peak_leftover_cnt;
842  buf2.reset(new Sample[to_do]);
843 
844  /* the remnants */
845  memcpy (buf2.get(), peak_leftovers, peak_leftover_cnt * sizeof (Sample));
846 
847  /* the new stuff */
848  memcpy (buf2.get()+peak_leftover_cnt, buf, cnt * sizeof (Sample));
849 
850  /* no more leftovers */
851  peak_leftover_cnt = 0;
852 
853  /* use the temporary buffer */
854  buf = buf2.get();
855 
856  /* make sure that when we write into the peakfile, we startup where we left off */
857 
858  first_frame = peak_leftover_frame;
859 
860  } else {
861  to_do = cnt;
862  }
863 
864  boost::scoped_array<PeakData> peakbuf(new PeakData[(to_do/fpp)+1]);
865  peaks_computed = 0;
866  current_frame = first_frame;
867  frames_done = 0;
868 
869  while (to_do) {
870 
871  /* if some frames were passed in (i.e. we're not flushing leftovers)
872  and there are less than fpp to do, save them till
873  next time
874  */
875 
876  if (force && (to_do < fpp)) {
877  /* keep the left overs around for next time */
878 
879  if (peak_leftover_size < to_do) {
880  delete [] peak_leftovers;
881  peak_leftovers = new Sample[to_do];
882  peak_leftover_size = to_do;
883  }
884  memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
885  peak_leftover_cnt = to_do;
886  peak_leftover_frame = current_frame;
887 
888  /* done for now */
889 
890  break;
891  }
892 
893  framecnt_t this_time = min (fpp, to_do);
894 
895  peakbuf[peaks_computed].max = buf[0];
896  peakbuf[peaks_computed].min = buf[0];
897 
898  ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
899 
900  peaks_computed++;
901  buf += this_time;
902  to_do -= this_time;
903  frames_done += this_time;
904  current_frame += this_time;
905  }
906 
907  first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
908 
909  if (can_truncate_peaks()) {
910 
911  /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
912  the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
913  it does not cause single-extent allocation even for peakfiles of
914  less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
915  */
916 
917  off_t endpos = lseek (_peakfile_fd, 0, SEEK_END);
918  off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
919 
920  if (endpos < target_length) {
921  DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
922  if (ftruncate (_peakfile_fd, target_length)) {
923  /* error doesn't actually matter so continue on without testing */
924  }
925  }
926  }
927 
928 
929  off_t offset = lseek(_peakfile_fd, first_peak_byte, SEEK_SET);
930 
931  if (offset != first_peak_byte) {
932  error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
933  return -1;
934  }
935 
936  ssize_t bytes_to_write = sizeof (PeakData) * peaks_computed;
937 
938  ssize_t bytes_written = ::write (_peakfile_fd, peakbuf.get(), bytes_to_write);
939 
940  if (bytes_written != bytes_to_write) {
941  error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
942  return -1;
943  }
944 
945  _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + bytes_to_write));
946 
947  if (frames_done) {
949  PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
950  if (intermediate_peaks_ready) {
951  PeaksReady (); /* EMIT SIGNAL */
952  }
953  }
954 
955  return 0;
956 }
957 
958 void
960 {
961  if (_peakfile_fd < 0) {
962  error << string_compose (_("programming error: %1"), "AudioSource::truncate_peakfile() called without open peakfile descriptor")
963  << endmsg;
964  return;
965  }
966 
967  /* truncate the peakfile down to its natural length if necessary */
968 
969  off_t end = lseek (_peakfile_fd, 0, SEEK_END);
970 
971  if (end > _peak_byte_max) {
972  DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
973  if (ftruncate (_peakfile_fd, _peak_byte_max)) {
974  error << string_compose (_("could not truncate peakfile %1 to %2 (error: %3)"),
975  peakpath, _peak_byte_max, errno) << endmsg;
976  }
977  }
978 }
979 
981 AudioSource::available_peaks (double zoom_factor) const
982 {
983  if (zoom_factor < _FPP) {
984  return length(_timeline_position); // peak data will come from the audio file
985  }
986 
987  /* peak data comes from peakfile, but the filesize might not represent
988  the valid data due to ftruncate optimizations, so use _peak_byte_max state.
989  XXX - there might be some atomicity issues here, we should probably add a lock,
990  but _peak_byte_max only monotonically increases after initialization.
991  */
992 
993  off_t end = _peak_byte_max;
994 
995  return (end/sizeof(PeakData)) * _FPP;
996 }
997 
998 void
1000 {
1002 
1003  if (_peaks_built) {
1004  PeaksReady (); /* EMIT SIGNAL */
1005  }
1006 }
1007 
1008 void
1010 {
1012 
1013 
1014  /* Note: we don't need any buffers allocated until
1015  a level 1 audiosource is created, at which
1016  time we'll call ::ensure_buffers_for_level()
1017  with the right value and do the right thing.
1018  */
1019 
1020  if (!_mixdown_buffers.empty()) {
1022  }
1023 }
1024 
1025 void
1027 {
1029  ensure_buffers_for_level_locked (level, frame_rate);
1030 }
1031 
1032 void
1034 {
1035  framecnt_t nframes = (framecnt_t) floor (Config->get_audio_playback_buffer_seconds() * frame_rate);
1036 
1037  /* this may be called because either "level" or "frame_rate" have
1038  * changed. and it may be called with "level" smaller than the current
1039  * number of buffers, because a new compound region has been created at
1040  * a more shallow level than the deepest one we currently have.
1041  */
1042 
1043  uint32_t limit = max ((size_t) level, _mixdown_buffers.size());
1044 
1045  _mixdown_buffers.clear ();
1046  _gain_buffers.clear ();
1047 
1048  for (uint32_t n = 0; n < limit; ++n) {
1049  _mixdown_buffers.push_back (boost::shared_array<Sample> (new Sample[nframes]));
1050  _gain_buffers.push_back (boost::shared_array<gain_t> (new gain_t[nframes]));
1051  }
1052 }
Flag _flags
Definition: source.h:119
#define _FPP
Definition: audiosource.cc:77
LIBARDOUR_API uint64_t Peaks
Definition: debug.cc:34
int build_peaks_from_scratch()
Definition: audiosource.cc:675
framecnt_t _length
Definition: audiosource.h:127
virtual std::string find_broken_peakfile(std::string, std::string audio_path)
Definition: audiosource.h:142
int read_peaks(PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt, double samples_per_visual_peak) const
Definition: audiosource.cc:330
virtual ~AudioSource()
Definition: audiosource.cc:114
const std::string & value() const
Definition: xml++.h:159
int prepare_for_peakfile_writes()
Definition: audiosource.cc:738
static std::vector< boost::shared_array< Sample > > _mixdown_buffers
Definition: audiosource.h:120
static bool _build_peakfiles
Definition: audiosource.h:110
Glib::Threads::Mutex::Lock Lock
Definition: source.h:54
waveform clip level
framepos_t peak_leftover_frame
Definition: audiosource.h:167
size_t _last_raw_map_length
Definition: audiosource.h:172
Definition: Beats.hpp:239
LIBPBD_API Transmitter error
std::string _captured_for
Definition: audiosource.h:129
int rename_peakfile(std::string newpath)
Definition: audiosource.cc:220
framepos_t _timeline_position
Definition: source.h:121
float gain_t
Definition: types.h:58
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
Sample * peak_leftovers
Definition: audiosource.h:166
PeakDatum max
Definition: types.h:489
virtual bool empty() const
Definition: audiosource.cc:155
virtual framecnt_t read(Sample *dst, framepos_t start, framecnt_t cnt, int channel=0) const
Definition: audiosource.cc:312
#define _(Text)
Definition: i18n.h:11
virtual std::string peak_path(std::string audio_path)=0
XMLNode & get_state()
Definition: audiosource.cc:131
void update_length(framecnt_t cnt)
Definition: audiosource.cc:167
XMLNode & get_state()
Definition: source.cc:93
int initialize_peakfile(std::string path)
Definition: audiosource.cc:239
int64_t framecnt_t
Definition: types.h:76
XMLProperty * property(const char *)
Definition: xml++.cc:413
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
float Sample
Definition: types.h:54
virtual framecnt_t write_unlocked(Sample *dst, framecnt_t cnt)=0
PBD::Signal2< void, framepos_t, framepos_t > PeakRangeReady
Definition: audiosource.h:78
PeakDatum min
Definition: types.h:488
framecnt_t peak_leftover_cnt
Definition: audiosource.h:164
static void allocate_working_buffers(framecnt_t framerate)
virtual void mark_streaming_write_completed(const Lock &lock)
Definition: audiosource.cc:999
Definition: amp.h:29
Sample PeakDatum
Definition: types.h:486
std::string peakpath
Definition: audiosource.h:128
static bool _build_missing_peakfiles
Definition: audiosource.h:109
virtual bool can_truncate_peaks() const
Definition: audiosource.h:66
void done_with_peakfile_writes(bool done=true)
Definition: audiosource.cc:748
#define DEBUG_TRACE(bits, str)
Definition: debug.h:55
PBD::Signal0< void > PeaksReady
Definition: audiosource.h:77
int64_t framepos_t
Definition: types.h:66
static int loading_state_version
Definition: stateful.h:90
PBD::Property< std::string > _name
boost::scoped_array< PeakData > peak_cache
Definition: audiosource.h:173
static Glib::Threads::Mutex _level_buffer_lock
Definition: audiosource.h:122
XMLProperty * add_property(const char *name, const std::string &value)
LIBARDOUR_API find_peaks_t find_peaks
Definition: globals.cc:130
const char * name
static void ensure_buffers_for_level(uint32_t, framecnt_t)
Definition: xml++.h:95
static void ensure_buffers_for_level_locked(uint32_t, framecnt_t)
Definition: debug.h:30
virtual framecnt_t write(Sample *src, framecnt_t cnt)
Definition: audiosource.cc:321
static std::vector< boost::shared_array< gain_t > > _gain_buffers
Definition: audiosource.h:121
int set_state(const XMLNode &, int version)
Definition: audiosource.cc:143
virtual framecnt_t available_peaks(double zoom) const
Definition: audiosource.cc:981
framecnt_t peak_leftover_size
Definition: audiosource.h:165
virtual int read_peaks_with_fpp(PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt, double samples_per_visual_peak, framecnt_t fpp) const
Definition: audiosource.cc:340
virtual framecnt_t read_unlocked(Sample *dst, framepos_t start, framecnt_t cnt) const =0
Glib::Threads::Mutex _lock
Definition: source.h:123
bool peaks_ready(boost::function< void()> callWhenReady, PBD::ScopedConnection **connection_created_if_not_ready, PBD::EventLoop *event_loop) const
Definition: audiosource.cc:189
framecnt_t length(framepos_t pos) const
Definition: audiosource.cc:161
int compute_and_write_peaks(Sample *buf, framecnt_t first_frame, framecnt_t cnt, bool force, bool intermediate_peaks_ready_signal)
Definition: audiosource.cc:766
#define MISSING_INVALIDATOR
Definition: event_loop.h:86
Glib::Threads::Mutex _peaks_ready_lock
Definition: audiosource.h:161
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208