Optimize automation-event process splitting
[ardour.git] / libs / ardour / sndfilesource.cc
1 /*
2     Copyright (C) 2006 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 WAF_BUILD
21 #include "libardour-config.h"
22 #endif
23
24 #include <cstring>
25 #include <cerrno>
26 #include <climits>
27 #include <cstdarg>
28 #include <fcntl.h>
29
30 #include <sys/stat.h>
31
32 #include <glib.h>
33 #include "pbd/gstdio_compat.h"
34
35 #include <glibmm/convert.h>
36 #include <glibmm/fileutils.h>
37 #include <glibmm/miscutils.h>
38
39 #include "ardour/runtime_functions.h"
40 #include "ardour/sndfilesource.h"
41 #include "ardour/sndfile_helpers.h"
42 #include "ardour/utils.h"
43 #include "ardour/session.h"
44
45 #include "pbd/i18n.h"
46
47 using namespace std;
48 using namespace ARDOUR;
49 using namespace PBD;
50 using std::string;
51
52 gain_t* SndFileSource::out_coefficient = 0;
53 gain_t* SndFileSource::in_coefficient = 0;
54 samplecnt_t SndFileSource::xfade_samples = 64;
55 const Source::Flag SndFileSource::default_writable_flags = Source::Flag (
56                 Source::Writable |
57                 Source::Removable |
58                 Source::RemovableIfEmpty |
59                 Source::CanRename );
60
61 SndFileSource::SndFileSource (Session& s, const XMLNode& node)
62         : Source(s, node)
63         , AudioFileSource (s, node)
64         , _sndfile (0)
65         , _broadcast_info (0)
66         , _capture_start (false)
67         , _capture_end (false)
68         , file_pos (0)
69         , xfade_buf (0)
70 {
71         init_sndfile ();
72
73         assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
74         existence_check ();
75
76         if (open()) {
77                 throw failed_constructor ();
78         }
79 }
80
81 /** Constructor for existing external-to-session files.
82     Files created this way are never writable or removable
83 */
84 SndFileSource::SndFileSource (Session& s, const string& path, int chn, Flag flags)
85         : Source(s, DataType::AUDIO, path, flags)
86           /* note that the origin of an external file is itself */
87         , AudioFileSource (s, path, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
88         , _sndfile (0)
89         , _broadcast_info (0)
90         , _capture_start (false)
91         , _capture_end (false)
92         , file_pos (0)
93         , xfade_buf (0)
94 {
95         _channel = chn;
96
97         init_sndfile ();
98
99         assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
100         existence_check ();
101
102         if (open()) {
103                 throw failed_constructor ();
104         }
105 }
106
107 /** This constructor is used to construct new internal-to-session files,
108     not open existing ones.
109 */
110 SndFileSource::SndFileSource (Session& s, const string& path, const string& origin,
111                               SampleFormat sfmt, HeaderFormat hf, samplecnt_t rate, Flag flags)
112         : Source(s, DataType::AUDIO, path, flags)
113         , AudioFileSource (s, path, origin, flags, sfmt, hf)
114         , _sndfile (0)
115         , _broadcast_info (0)
116         , _capture_start (false)
117         , _capture_end (false)
118         , file_pos (0)
119         , xfade_buf (0)
120 {
121         int fmt = 0;
122
123         init_sndfile ();
124
125         assert (!Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
126         existence_check ();
127
128         _file_is_new = true;
129
130         switch (hf) {
131         case CAF:
132                 fmt = SF_FORMAT_CAF;
133                 _flags = Flag (_flags & ~Broadcast);
134                 break;
135
136         case FLAC:
137                 fmt = SF_FORMAT_FLAC;
138                 if (sfmt == FormatFloat) {
139                         sfmt = FormatInt24;
140                 }
141                 _flags = Flag (_flags & ~Broadcast);
142                 _flags = Flag (_flags & ~Destructive); // XXX or force WAV if destructive?
143                 break;
144
145         case AIFF:
146                 fmt = SF_FORMAT_AIFF;
147                 _flags = Flag (_flags & ~Broadcast);
148                 break;
149
150         case BWF:
151                 fmt = SF_FORMAT_WAV;
152                 _flags = Flag (_flags | Broadcast);
153                 break;
154
155         case WAVE:
156                 fmt = SF_FORMAT_WAV;
157                 _flags = Flag (_flags & ~Broadcast);
158                 break;
159
160         case WAVE64:
161                 fmt = SF_FORMAT_W64;
162                 _flags = Flag (_flags & ~Broadcast);
163                 break;
164
165         case RF64_WAV:
166                 fmt = SF_FORMAT_RF64;
167                 _flags = Flag (_flags & ~Broadcast);
168                 _flags = Flag (_flags | RF64_RIFF);
169                 break;
170
171         case MBWF:
172                 fmt = SF_FORMAT_RF64;
173                 _flags = Flag (_flags | Broadcast);
174                 _flags = Flag (_flags | RF64_RIFF);
175                 break;
176
177         case RF64:
178                 fmt = SF_FORMAT_RF64;
179                 _flags = Flag (_flags & ~Broadcast);
180                 break;
181
182         default:
183                 fatal << string_compose (_("programming error: %1"), X_("unsupported audio header format requested")) << endmsg;
184                 abort(); /*NOTREACHED*/
185                 break;
186
187         }
188
189         switch (sfmt) {
190         case FormatFloat:
191                 fmt |= SF_FORMAT_FLOAT;
192                 break;
193
194         case FormatInt24:
195                 fmt |= SF_FORMAT_PCM_24;
196                 break;
197
198         case FormatInt16:
199                 fmt |= SF_FORMAT_PCM_16;
200                 break;
201         }
202
203         _info.channels = 1;
204         _info.samplerate = rate;
205         _info.format = fmt;
206
207         if (_flags & Destructive) {
208                 if (open()) {
209                         throw failed_constructor();
210                 }
211         } else {
212                 /* normal mode: do not open the file here - do that in {read,write}_unlocked() as needed
213                  */
214         }
215 }
216
217 /** Constructor to be called for recovering files being used for
218  * capture. They are in-session, they already exist, they should not
219  * be writable. They are an odd hybrid (from a constructor point of
220  * view) of the previous two constructors.
221  */
222 SndFileSource::SndFileSource (Session& s, const string& path, int chn)
223         : Source (s, DataType::AUDIO, path, Flag (0))
224           /* the final boolean argument is not used, its value is irrelevant. see audiofilesource.h for explanation */
225         , AudioFileSource (s, path, Flag (0))
226         , _sndfile (0)
227         , _broadcast_info (0)
228         , _capture_start (false)
229         , _capture_end (false)
230         , file_pos (0)
231         , xfade_buf (0)
232 {
233         _channel = chn;
234
235         init_sndfile ();
236
237         assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
238         existence_check ();
239
240         if (open()) {
241                 throw failed_constructor ();
242         }
243 }
244
245 /** Constructor to losslessly compress existing source to flac */
246 SndFileSource::SndFileSource (Session& s, const AudioFileSource& other, const string& path, bool use16bits, Progress* progress)
247         : Source(s, DataType::AUDIO, path, Flag ((other.flags () | default_writable_flags | NoPeakFile) & ~RF64_RIFF))
248         , AudioFileSource (s, path, "", Flag ((other.flags () | default_writable_flags | NoPeakFile) & ~RF64_RIFF), /*unused*/ FormatFloat, /*unused*/ WAVE64)
249         , _sndfile (0)
250         , _broadcast_info (0)
251         , _capture_start (false)
252         , _capture_end (false)
253         , file_pos (0)
254         , xfade_buf (0)
255 {
256         if (other.readable_length () == 0) {
257                 throw failed_constructor();
258         }
259
260         assert (!Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
261
262         _channel = 0;
263         init_sndfile ();
264
265         _file_is_new = true;
266
267         _info.channels = 1;
268         _info.samplerate = other.sample_rate ();
269         _info.format = SF_FORMAT_FLAC | (use16bits ? SF_FORMAT_PCM_16 : SF_FORMAT_PCM_24);
270
271         /* flac is either read or write -- never both,
272          * so we need to special-case ::open () */
273 #ifdef PLATFORM_WINDOWS
274         int fd = g_open (_path.c_str(), O_CREAT | O_RDWR, 0644);
275 #else
276         int fd = ::open (_path.c_str(), O_CREAT | O_RDWR, 0644);
277 #endif
278         if (fd == -1) {
279                 throw failed_constructor();
280         }
281
282         _sndfile = sf_open_fd (fd, SFM_WRITE, &_info, true);
283
284         if (_sndfile == 0) {
285                 throw failed_constructor();
286         }
287
288 #if 0
289         /* setting flac compression quality above the default does not produce a significant size
290          * improvement (not for large raw recordings anyway, the_CLA tests 2017-10-02, >> 250MB files,
291          * ~1% smaller), but does have a significant encoding speed penalty.
292          *
293          * We still may expose this as option someday though, perhaps for opposite reason: "fast encoding"
294          */
295         double flac_quality = 1; // libsndfile uses range 0..1 (mapped to flac 0..8), default is (5/8)
296         if (sf_command (_sndfile, SFC_SET_COMPRESSION_LEVEL, &flac_quality, sizeof (double)) != SF_TRUE) {
297                 char errbuf[256];
298                 sf_error_str (_sndfile, errbuf, sizeof (errbuf) - 1);
299                 error << string_compose (_("Cannot set flac compression level: %1"), errbuf) << endmsg;
300         }
301 #endif
302
303         Sample buf[8192];
304         samplecnt_t off = 0;
305         float peak = 0;
306         float norm = 1.f;
307
308         /* normalize before converting to fixed point, calc gain factor */
309         samplecnt_t len = other.read (buf, off, 8192, other.channel ());
310         while (len > 0) {
311                 peak = compute_peak (buf, len, peak);
312                 off += len;
313                 len = other.read (buf, off, 8192, other.channel ());
314                 if (progress) {
315                         progress->set_progress (0.5f * (float) off / other.readable_length ());
316                 }
317         }
318
319         if (peak > 0) {
320                 _gain *= peak;
321                 norm = 1.f / peak;
322         }
323
324         /* copy file */
325         off = 0;
326         len = other.read (buf, off, 8192, other.channel ());
327         while (len > 0) {
328                 if (norm != 1.f) {
329                         for (samplecnt_t i = 0; i < len; ++i) {
330                                 buf[i] *= norm;
331                         }
332                 }
333                 write (buf, len);
334                 off += len;
335                 len = other.read (buf, off, 8192, other.channel ());
336                 if (progress) {
337                         progress->set_progress (0.5f + 0.5f * (float) off / other.readable_length ());
338                 }
339         }
340 }
341
342 void
343 SndFileSource::init_sndfile ()
344 {
345         /* although libsndfile says we don't need to set this,
346            valgrind and source code shows us that we do.
347         */
348
349         memset (&_info, 0, sizeof(_info));
350
351         if (destructive()) {
352                 xfade_buf = new Sample[xfade_samples];
353                 _timeline_position = header_position_offset;
354         }
355
356         AudioFileSource::HeaderPositionOffsetChanged.connect_same_thread (header_position_connection, boost::bind (&SndFileSource::handle_header_position_change, this));
357 }
358
359 void
360 SndFileSource::close ()
361 {
362         if (_sndfile) {
363                 sf_close (_sndfile);
364                 _sndfile = 0;
365                 file_closed ();
366         }
367 }
368
369 int
370 SndFileSource::open ()
371 {
372         if (_sndfile) {
373                 return 0;
374         }
375
376 // We really only want to use g_open for all platforms but because of this
377 // method(SndfileSource::open), the compiler(or at least GCC) is confused
378 // because g_open will expand to "open" on non-POSIX systems and needs the
379 // global namespace qualifer. The problem is since since C99 ::g_open will
380 // apparently expand to ":: open"
381 #ifdef PLATFORM_WINDOWS
382         int fd = g_open (_path.c_str(), writable() ? O_CREAT | O_RDWR : O_RDONLY, writable() ? 0644 : 0444);
383 #else
384         int fd = ::open (_path.c_str(), writable() ? O_CREAT | O_RDWR : O_RDONLY, writable() ? 0644 : 0444);
385 #endif
386
387         if (fd == -1) {
388                 error << string_compose (
389                              _ ("SndFileSource: cannot open file \"%1\" for %2"),
390                              _path,
391                              (writable () ? "read+write" : "reading")) << endmsg;
392                 return -1;
393         }
394
395         if ((_info.format & SF_FORMAT_TYPEMASK ) == SF_FORMAT_FLAC) {
396                 assert (!destructive());
397                 _sndfile = sf_open_fd (fd, writable () ? SFM_WRITE : SFM_READ, &_info, true);
398         } else {
399                 _sndfile = sf_open_fd (fd, writable() ? SFM_RDWR : SFM_READ, &_info, true);
400         }
401
402         if (_sndfile == 0) {
403                 char errbuf[1024];
404                 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
405 #ifndef HAVE_COREAUDIO
406                 /* if we have CoreAudio, we will be falling back to that if libsndfile fails,
407                    so we don't want to see this message.
408                 */
409
410                 cerr << "failed to open " << _path << " with name " << _name << endl;
411
412                 error << string_compose(_("SndFileSource: cannot open file \"%1\" for %2 (%3)"),
413                                         _path, (writable() ? "read+write" : "reading"), errbuf) << endmsg;
414 #endif
415                 return -1;
416         }
417
418         if (_channel >= _info.channels) {
419 #ifndef HAVE_COREAUDIO
420                 error << string_compose(_("SndFileSource: file only contains %1 channels; %2 is invalid as a channel number"), _info.channels, _channel) << endmsg;
421 #endif
422                 sf_close (_sndfile);
423                 _sndfile = 0;
424                 return -1;
425         }
426
427         _length = _info.frames;
428
429 #ifdef HAVE_RF64_RIFF
430         if (_file_is_new && _length == 0 && writable()) {
431                 if (_flags & RF64_RIFF) {
432                         if (sf_command (_sndfile, SFC_RF64_AUTO_DOWNGRADE, 0, 0) != SF_TRUE) {
433                                 char errbuf[256];
434                                 sf_error_str (_sndfile, errbuf, sizeof (errbuf) - 1);
435                                 error << string_compose (_("Cannot mark RF64 audio file for automatic downgrade to WAV: %1"), errbuf)
436                                       << endmsg;
437                         }
438                 }
439         }
440 #endif
441
442         if (!_broadcast_info) {
443                 _broadcast_info = new BroadcastInfo;
444         }
445
446         bool bwf_info_exists = _broadcast_info->load_from_file (_sndfile);
447
448         if (_file_is_new && _length == 0 && writable() && !bwf_info_exists) {
449                 /* newly created files will not have a BWF header at this point in time.
450                  * Import will have called Source::set_timeline_position() if one exists
451                  * in the original. */
452                 header_position_offset = _timeline_position;
453         }
454
455         /* Set our timeline position to either the time reference from a BWF header or the current
456            start of the session.
457         */
458         set_timeline_position (bwf_info_exists ? _broadcast_info->get_time_reference() : header_position_offset);
459
460         if (_length != 0 && !bwf_info_exists) {
461                 delete _broadcast_info;
462                 _broadcast_info = 0;
463                 _flags = Flag (_flags & ~Broadcast);
464         }
465
466         /* Set the broadcast flag if the BWF info is already there. We need
467          * this when recovering or using existing files.
468          */
469
470         if (bwf_info_exists) {
471                 _flags = Flag (_flags | Broadcast);
472         }
473
474         if (writable()) {
475                 sf_command (_sndfile, SFC_SET_UPDATE_HEADER_AUTO, 0, SF_FALSE);
476
477                 if (_flags & Broadcast) {
478
479                         if (!_broadcast_info) {
480                                 _broadcast_info = new BroadcastInfo;
481                         }
482
483                         _broadcast_info->set_from_session (_session, header_position_offset);
484                         _broadcast_info->set_description (string_compose ("BWF %1", _name));
485
486                         if (!_broadcast_info->write_to_file (_sndfile)) {
487                                 error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"),
488                                                          _path, _broadcast_info->get_error())
489                                       << endmsg;
490                                 _flags = Flag (_flags & ~Broadcast);
491                                 delete _broadcast_info;
492                                 _broadcast_info = 0;
493                         }
494                 }
495         }
496
497         return 0;
498 }
499
500 SndFileSource::~SndFileSource ()
501 {
502         close ();
503         delete _broadcast_info;
504         delete [] xfade_buf;
505 }
506
507 float
508 SndFileSource::sample_rate () const
509 {
510         return _info.samplerate;
511 }
512
513 samplecnt_t
514 SndFileSource::read_unlocked (Sample *dst, samplepos_t start, samplecnt_t cnt) const
515 {
516         assert (cnt >= 0);
517
518         samplecnt_t nread;
519         float *ptr;
520         samplecnt_t real_cnt;
521         samplepos_t file_cnt;
522
523         if (writable() && !_sndfile) {
524                 /* file has not been opened yet - nothing written to it */
525                 memset (dst, 0, sizeof (Sample) * cnt);
526                 return cnt;
527         }
528
529         if (const_cast<SndFileSource*>(this)->open()) {
530                 error << string_compose (_("could not open file %1 for reading."), _path) << endmsg;
531                 return 0;
532         }
533
534         if (start > _length) {
535
536                 /* read starts beyond end of data, just memset to zero */
537
538                 file_cnt = 0;
539
540         } else if (start + cnt > _length) {
541
542                 /* read ends beyond end of data, read some, memset the rest */
543
544                 file_cnt = _length - start;
545
546         } else {
547
548                 /* read is entirely within data */
549
550                 file_cnt = cnt;
551         }
552
553         assert (file_cnt >= 0);
554
555         if (file_cnt != cnt) {
556                 samplepos_t delta = cnt - file_cnt;
557                 memset (dst+file_cnt, 0, sizeof (Sample) * delta);
558         }
559
560         if (file_cnt) {
561
562                 if (sf_seek (_sndfile, (sf_count_t) start, SEEK_SET|SFM_READ) != (sf_count_t) start) {
563                         char errbuf[256];
564                         sf_error_str (0, errbuf, sizeof (errbuf) - 1);
565                         error << string_compose(_("SndFileSource: could not seek to sample %1 within %2 (%3)"), start, _name.val().substr (1), errbuf) << endmsg;
566                         return 0;
567                 }
568
569                 if (_info.channels == 1) {
570                         samplecnt_t ret = sf_read_float (_sndfile, dst, file_cnt);
571                         if (ret != file_cnt) {
572                                 char errbuf[256];
573                                 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
574                                 error << string_compose(_("SndFileSource: @ %1 could not read %2 within %3 (%4) (len = %5, ret was %6)"), start, file_cnt, _name.val().substr (1), errbuf, _length, ret) << endl;
575                         }
576                         if (_gain != 1.f) {
577                                 for (samplecnt_t i = 0; i < ret; ++i) {
578                                         dst[i] *= _gain;
579                                 }
580                         }
581                         return ret;
582                 }
583         }
584
585         real_cnt = cnt * _info.channels;
586
587         Sample* interleave_buf = get_interleave_buffer (real_cnt);
588
589         nread = sf_read_float (_sndfile, interleave_buf, real_cnt);
590         ptr = interleave_buf + _channel;
591         nread /= _info.channels;
592
593         /* stride through the interleaved data */
594
595         if (_gain != 1.f) {
596                 for (samplecnt_t n = 0; n < nread; ++n) {
597                         dst[n] = *ptr * _gain;
598                         ptr += _info.channels;
599                 }
600         } else {
601                 for (samplecnt_t n = 0; n < nread; ++n) {
602                         dst[n] = *ptr;
603                         ptr += _info.channels;
604                 }
605         }
606
607         return nread;
608 }
609
610 samplecnt_t
611 SndFileSource::write_unlocked (Sample *data, samplecnt_t cnt)
612 {
613         if (open()) {
614                 return 0; // failure
615         }
616
617         if (destructive()) {
618                 return destructive_write_unlocked (data, cnt);
619         } else {
620                 return nondestructive_write_unlocked (data, cnt);
621         }
622 }
623
624 samplecnt_t
625 SndFileSource::nondestructive_write_unlocked (Sample *data, samplecnt_t cnt)
626 {
627         if (!writable()) {
628                 warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
629                 return 0;
630         }
631
632         if (_info.channels != 1) {
633                 fatal << string_compose (_("programming error: %1 %2"), X_("SndFileSource::write called on non-mono file"), _path) << endmsg;
634                 abort(); /*NOTREACHED*/
635                 return 0;
636         }
637
638         samplepos_t sample_pos = _length;
639
640         if (write_float (data, sample_pos, cnt) != cnt) {
641                 return 0;
642         }
643
644         update_length (_length + cnt);
645
646         if (_build_peakfiles) {
647                 compute_and_write_peaks (data, sample_pos, cnt, true, true);
648         }
649
650         return cnt;
651 }
652
653 samplecnt_t
654 SndFileSource::destructive_write_unlocked (Sample* data, samplecnt_t cnt)
655 {
656         if (!writable()) {
657                 warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
658                 return 0;
659         }
660
661         if (_capture_start && _capture_end) {
662
663                 /* start and end of capture both occur within the data we are writing,
664                    so do both crossfades.
665                 */
666
667                 _capture_start = false;
668                 _capture_end = false;
669
670                 /* move to the correct location place */
671                 file_pos = capture_start_sample - _timeline_position;
672
673                 // split cnt in half
674                 samplecnt_t subcnt = cnt / 2;
675                 samplecnt_t ofilepos = file_pos;
676
677                 // fade in
678                 if (crossfade (data, subcnt, 1) != subcnt) {
679                         return 0;
680                 }
681
682                 file_pos += subcnt;
683                 Sample * tmpdata = data + subcnt;
684
685                 // fade out
686                 subcnt = cnt - subcnt;
687                 if (crossfade (tmpdata, subcnt, 0) != subcnt) {
688                         return 0;
689                 }
690
691                 file_pos = ofilepos; // adjusted below
692
693         } else if (_capture_start) {
694
695                 /* start of capture both occur within the data we are writing,
696                    so do the fade in
697                 */
698
699                 _capture_start = false;
700                 _capture_end = false;
701
702                 /* move to the correct location place */
703                 file_pos = capture_start_sample - _timeline_position;
704
705                 if (crossfade (data, cnt, 1) != cnt) {
706                         return 0;
707                 }
708
709         } else if (_capture_end) {
710
711                 /* end of capture both occur within the data we are writing,
712                    so do the fade out
713                 */
714
715                 _capture_start = false;
716                 _capture_end = false;
717
718                 if (crossfade (data, cnt, 0) != cnt) {
719                         return 0;
720                 }
721
722         } else {
723
724                 /* in the middle of recording */
725
726                 if (write_float (data, file_pos, cnt) != cnt) {
727                         return 0;
728                 }
729         }
730
731         update_length (file_pos + cnt);
732
733         if (_build_peakfiles) {
734                 compute_and_write_peaks (data, file_pos, cnt, true, true);
735         }
736
737         file_pos += cnt;
738
739         return cnt;
740 }
741
742 int
743 SndFileSource::update_header (samplepos_t when, struct tm& now, time_t tnow)
744 {
745         set_timeline_position (when);
746
747         if (_flags & Broadcast) {
748                 if (setup_broadcast_info (when, now, tnow)) {
749                         return -1;
750                 }
751         }
752
753         return flush_header ();
754 }
755
756 int
757 SndFileSource::flush_header ()
758 {
759         if (!writable()) {
760                 warning << string_compose (_("attempt to flush a non-writable audio file source (%1)"), _path) << endmsg;
761                 return -1;
762         }
763
764         if (_sndfile == 0) {
765                 error << string_compose (_("could not allocate file %1 to write header"), _path) << endmsg;
766                 return -1;
767         }
768
769         int const r = sf_command (_sndfile, SFC_UPDATE_HEADER_NOW, 0, 0) != SF_TRUE;
770
771         return r;
772 }
773
774 void
775 SndFileSource::flush ()
776 {
777         if (!writable()) {
778                 warning << string_compose (_("attempt to flush a non-writable audio file source (%1)"), _path) << endmsg;
779                 return;
780         }
781
782         if (_sndfile == 0) {
783                 error << string_compose (_("could not allocate file %1 to flush contents"), _path) << endmsg;
784                 return;
785         }
786
787         // Hopefully everything OK
788         sf_write_sync (_sndfile);
789 }
790
791 int
792 SndFileSource::setup_broadcast_info (samplepos_t /*when*/, struct tm& now, time_t /*tnow*/)
793 {
794         if (!writable()) {
795                 warning << string_compose (_("attempt to store broadcast info in a non-writable audio file source (%1)"), _path) << endmsg;
796                 return -1;
797         }
798
799         if (!_sndfile) {
800                 warning << string_compose (_("attempt to set BWF info for an un-opened audio file source (%1)"), _path) << endmsg;
801                 return -1;
802         }
803
804         if (!(_flags & Broadcast) || !_broadcast_info) {
805                 return 0;
806         }
807
808         _broadcast_info->set_originator_ref_from_session (_session);
809         _broadcast_info->set_origination_time (&now);
810
811         /* now update header position taking header offset into account */
812
813         set_header_timeline_position ();
814
815         return 0;
816 }
817
818 void
819 SndFileSource::set_header_timeline_position ()
820 {
821         if (!(_flags & Broadcast)) {
822                 return;
823         }
824         assert (_broadcast_info);
825
826         _broadcast_info->set_time_reference (_timeline_position);
827
828         if (_sndfile == 0 || !_broadcast_info->write_to_file (_sndfile)) {
829                 error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"),
830                                            _path, _broadcast_info->get_error())
831                       << endmsg;
832                 _flags = Flag (_flags & ~Broadcast);
833                 delete _broadcast_info;
834                 _broadcast_info = 0;
835         }
836 }
837
838 samplecnt_t
839 SndFileSource::write_float (Sample* data, samplepos_t sample_pos, samplecnt_t cnt)
840 {
841         if ((_info.format & SF_FORMAT_TYPEMASK ) == SF_FORMAT_FLAC) {
842                 assert (_length == sample_pos);
843         }
844         else if (_sndfile == 0 || sf_seek (_sndfile, sample_pos, SEEK_SET|SFM_WRITE) < 0) {
845                 char errbuf[256];
846                 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
847                 error << string_compose (_("%1: cannot seek to %2 (libsndfile error: %3)"), _path, sample_pos, errbuf) << endmsg;
848                 return 0;
849         }
850
851         if (sf_writef_float (_sndfile, data, cnt) != (ssize_t) cnt) {
852                 return 0;
853         }
854
855         return cnt;
856 }
857
858 samplepos_t
859 SndFileSource::natural_position() const
860 {
861         return _timeline_position;
862 }
863
864 void
865 SndFileSource::clear_capture_marks ()
866 {
867         _capture_start = false;
868         _capture_end = false;
869 }
870
871 /** @param pos Capture start position in session samples */
872 void
873 SndFileSource::mark_capture_start (samplepos_t pos)
874 {
875         if (destructive()) {
876                 if (pos < _timeline_position) {
877                         _capture_start = false;
878                 } else {
879                         _capture_start = true;
880                         capture_start_sample = pos;
881                 }
882         }
883 }
884
885 void
886 SndFileSource::mark_capture_end()
887 {
888         if (destructive()) {
889                 _capture_end = true;
890         }
891 }
892
893 samplecnt_t
894 SndFileSource::crossfade (Sample* data, samplecnt_t cnt, int fade_in)
895 {
896         samplecnt_t xfade = min (xfade_samples, cnt);
897         samplecnt_t nofade = cnt - xfade;
898         Sample* fade_data = 0;
899         samplepos_t fade_position = 0; // in samples
900         ssize_t retval;
901         samplecnt_t file_cnt;
902
903         if (fade_in) {
904                 fade_position = file_pos;
905                 fade_data = data;
906         } else {
907                 fade_position = file_pos + nofade;
908                 fade_data = data + nofade;
909         }
910
911         if (fade_position > _length) {
912
913                 /* read starts beyond end of data, just memset to zero */
914
915                 file_cnt = 0;
916
917         } else if (fade_position + xfade > _length) {
918
919                 /* read ends beyond end of data, read some, memset the rest */
920
921                 file_cnt = _length - fade_position;
922
923         } else {
924
925                 /* read is entirely within data */
926
927                 file_cnt = xfade;
928         }
929
930         if (file_cnt) {
931
932                 if ((retval = read_unlocked (xfade_buf, fade_position, file_cnt)) != (ssize_t) file_cnt) {
933                         if (retval >= 0 && errno == EAGAIN) {
934                                 /* XXX - can we really trust that errno is meaningful here?  yes POSIX, i'm talking to you.
935                                  * short or no data there */
936                                 memset (xfade_buf, 0, xfade * sizeof(Sample));
937                         } else {
938                                 error << string_compose(_("SndFileSource: \"%1\" bad read retval: %2 of %5 (%3: %4)"), _path, retval, errno, strerror (errno), xfade) << endmsg;
939                                 return 0;
940                         }
941                 }
942         }
943
944         if (file_cnt != xfade) {
945                 samplecnt_t delta = xfade - file_cnt;
946                 memset (xfade_buf+file_cnt, 0, sizeof (Sample) * delta);
947         }
948
949         if (nofade && !fade_in) {
950                 if (write_float (data, file_pos, nofade) != nofade) {
951                         error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
952                         return 0;
953                 }
954         }
955
956         if (xfade == xfade_samples) {
957
958                 samplecnt_t n;
959
960                 /* use the standard xfade curve */
961
962                 if (fade_in) {
963
964                         /* fade new material in */
965
966                         for (n = 0; n < xfade; ++n) {
967                                 xfade_buf[n] = (xfade_buf[n] * out_coefficient[n]) + (fade_data[n] * in_coefficient[n]);
968                         }
969
970                 } else {
971
972
973                         /* fade new material out */
974
975                         for (n = 0; n < xfade; ++n) {
976                                 xfade_buf[n] = (xfade_buf[n] * in_coefficient[n]) + (fade_data[n] * out_coefficient[n]);
977                         }
978                 }
979
980         } else if (xfade < xfade_samples) {
981
982                 std::vector<gain_t> in(xfade);
983                 std::vector<gain_t> out(xfade);
984
985                 /* short xfade, compute custom curve */
986
987                 compute_equal_power_fades (xfade, &in[0], &out[0]);
988
989                 for (samplecnt_t n = 0; n < xfade; ++n) {
990                         xfade_buf[n] = (xfade_buf[n] * out[n]) + (fade_data[n] * in[n]);
991                 }
992
993         } else if (xfade) {
994
995                 /* long xfade length, has to be computed across several calls */
996
997         }
998
999         if (xfade) {
1000                 if (write_float (xfade_buf, fade_position, xfade) != xfade) {
1001                         error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
1002                         return 0;
1003                 }
1004         }
1005
1006         if (fade_in && nofade) {
1007                 if (write_float (data + xfade, file_pos + xfade, nofade) != nofade) {
1008                         error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
1009                         return 0;
1010                 }
1011         }
1012
1013         return cnt;
1014 }
1015
1016 samplepos_t
1017 SndFileSource::last_capture_start_sample () const
1018 {
1019         if (destructive()) {
1020                 return capture_start_sample;
1021         } else {
1022                 return 0;
1023         }
1024 }
1025
1026 void
1027 SndFileSource::handle_header_position_change ()
1028 {
1029         if (destructive()) {
1030                 if ( _length != 0 ) {
1031                         error << string_compose(_("Filesource: start time is already set for existing file (%1): Cannot change start time."), _path ) << endmsg;
1032                         //in the future, pop up a dialog here that allows user to regenerate file with new start offset
1033                 } else if (writable()) {
1034                         _timeline_position = header_position_offset;
1035                         set_header_timeline_position ();  //this will get flushed if/when the file is recorded to
1036                 }
1037         }
1038 }
1039
1040 void
1041 SndFileSource::setup_standard_crossfades (Session const & s, samplecnt_t rate)
1042 {
1043         /* This static method is assumed to have been called by the Session
1044            before any DFS's are created.
1045         */
1046
1047         xfade_samples = (samplecnt_t) floor ((s.config.get_destructive_xfade_msecs () / 1000.0) * rate);
1048
1049         delete [] out_coefficient;
1050         delete [] in_coefficient;
1051
1052         out_coefficient = new gain_t[xfade_samples];
1053         in_coefficient = new gain_t[xfade_samples];
1054
1055         compute_equal_power_fades (xfade_samples, in_coefficient, out_coefficient);
1056 }
1057
1058 void
1059 SndFileSource::set_timeline_position (samplepos_t pos)
1060 {
1061         // destructive track timeline postion does not change
1062         // except at instantion or when header_position_offset
1063         // (session start) changes
1064
1065         if (!destructive()) {
1066                 AudioFileSource::set_timeline_position (pos);
1067         }
1068 }
1069
1070 int
1071 SndFileSource::get_soundfile_info (const string& path, SoundFileInfo& info, string& error_msg)
1072 {
1073         SNDFILE *sf;
1074         SF_INFO sf_info;
1075         BroadcastInfo binfo;
1076
1077         sf_info.format = 0; // libsndfile says to clear this before sf_open().
1078
1079         if (path.empty() || Glib::file_test(path, Glib::FILE_TEST_IS_DIR)) {
1080                 return false;
1081         }
1082
1083 #ifdef PLATFORM_WINDOWS
1084         int fd = g_open (path.c_str(), O_RDONLY, 0444);
1085 #else
1086         int fd = ::open (path.c_str(), O_RDONLY, 0444);
1087 #endif
1088
1089         if (fd == -1) {
1090                 error << string_compose ( _("SndFileSource: cannot open file \"%1\" for reading"), path)
1091                       << endmsg;
1092                 return false;
1093         }
1094         if ((sf = sf_open_fd (fd, SFM_READ, &sf_info, true)) == 0) {
1095                 char errbuf[1024];
1096                 error_msg = sf_error_str (0, errbuf, sizeof (errbuf) - 1);
1097                 return false;
1098         }
1099
1100         info.samplerate  = sf_info.samplerate;
1101         info.channels    = sf_info.channels;
1102         info.length      = sf_info.frames;
1103
1104         string major = sndfile_major_format(sf_info.format);
1105         string minor = sndfile_minor_format(sf_info.format);
1106
1107         if (major.length() + minor.length() < 16) { /* arbitrary */
1108                 info.format_name = string_compose("%1/%2", major, minor);
1109         } else {
1110                 info.format_name = string_compose("%1\n%2", major, minor);
1111         }
1112
1113         info.timecode = binfo.load_from_file (sf) ? binfo.get_time_reference() : 0;
1114
1115         sf_close (sf);
1116
1117         return true;
1118 }
1119
1120 bool
1121 SndFileSource::one_of_several_channels () const
1122 {
1123         return _info.channels > 1;
1124 }
1125
1126 bool
1127 SndFileSource::clamped_at_unity () const
1128 {
1129         int const type = _info.format & SF_FORMAT_TYPEMASK;
1130         int const sub = _info.format & SF_FORMAT_SUBMASK;
1131         /* XXX: this may not be the full list of formats that are unclamped */
1132         return (sub != SF_FORMAT_FLOAT && sub != SF_FORMAT_DOUBLE && type != SF_FORMAT_OGG);
1133 }
1134
1135 void
1136 SndFileSource::file_closed ()
1137 {
1138         /* stupid libsndfile updated the headers on close,
1139            so touch the peakfile if it exists and has data
1140            to make sure its time is as new as the audio
1141            file.
1142         */
1143
1144         touch_peakfile ();
1145 }
1146
1147 void
1148 SndFileSource::set_path (const string& p)
1149 {
1150         FileSource::set_path (p);
1151 }
1152