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