2 Copyright (C) 2006 Paul Davis
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.
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.
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.
21 #include "libardour-config.h"
30 #include <sys/utsname.h>
33 #include <glibmm/miscutils.h>
35 #include "ardour/sndfilesource.h"
36 #include "ardour/sndfile_helpers.h"
37 #include "ardour/utils.h"
38 #include "ardour/version.h"
39 #include "ardour/rc_configuration.h"
40 #include "ardour/session.h"
45 using namespace ARDOUR;
49 gain_t* SndFileSource::out_coefficient = 0;
50 gain_t* SndFileSource::in_coefficient = 0;
51 framecnt_t SndFileSource::xfade_frames = 64;
52 const Source::Flag SndFileSource::default_writable_flags = Source::Flag (
55 Source::RemovableIfEmpty |
58 SndFileSource::SndFileSource (Session& s, const XMLNode& node)
60 , AudioFileSource (s, node)
65 throw failed_constructor ();
69 /** Files created this way are never writable or removable */
70 SndFileSource::SndFileSource (Session& s, const string& path, int chn, Flag flags)
71 : Source(s, DataType::AUDIO, path, flags)
72 /* note that the origin of an external file is itself */
73 , AudioFileSource (s, path, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
80 throw failed_constructor ();
84 /** This constructor is used to construct new files, not open existing ones. */
85 SndFileSource::SndFileSource (Session& s, const string& path, const string& origin,
86 SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
87 : Source(s, DataType::AUDIO, path, flags)
88 , AudioFileSource (s, path, origin, flags, sfmt, hf)
99 _flags = Flag (_flags & ~Broadcast);
103 fmt = SF_FORMAT_AIFF;
104 _flags = Flag (_flags & ~Broadcast);
109 _flags = Flag (_flags | Broadcast);
114 _flags = Flag (_flags & ~Broadcast);
119 _flags = Flag (_flags & ~Broadcast);
123 fatal << string_compose (_("programming error: %1"), X_("unsupported audio header format requested")) << endmsg;
131 fmt |= SF_FORMAT_FLOAT;
135 fmt |= SF_FORMAT_PCM_24;
139 fmt |= SF_FORMAT_PCM_16;
144 _info.samplerate = rate;
148 throw failed_constructor();
151 if (writable() && (_flags & Broadcast)) {
153 SNDFILE* sf = _descriptor->allocate ();
155 error << string_compose (_("could not allocate file %1"), _path) << endmsg;
156 throw failed_constructor ();
159 if (!_broadcast_info) {
160 _broadcast_info = new BroadcastInfo;
163 _broadcast_info->set_from_session (s, header_position_offset);
164 _broadcast_info->set_description (string_compose ("BWF %1", _name));
166 if (!_broadcast_info->write_to_file (sf)) {
167 error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"),
168 _path, _broadcast_info->get_error())
170 _flags = Flag (_flags & ~Broadcast);
171 delete _broadcast_info;
175 _descriptor->release ();
180 SndFileSource::init_sndfile ()
184 // lets try to keep the object initalizations here at the top
188 /* although libsndfile says we don't need to set this,
189 valgrind and source code shows us that we do.
192 memset (&_info, 0, sizeof(_info));
194 _capture_start = false;
195 _capture_end = false;
199 xfade_buf = new Sample[xfade_frames];
200 _timeline_position = header_position_offset;
203 AudioFileSource::HeaderPositionOffsetChanged.connect_same_thread (header_position_connection, boost::bind (&SndFileSource::handle_header_position_change, this));
207 SndFileSource::open ()
209 _descriptor = new SndFileDescriptor (_path, writable(), &_info);
210 _descriptor->Closed.connect_same_thread (file_manager_connection, boost::bind (&SndFileSource::file_closed, this));
211 SNDFILE* sf = _descriptor->allocate ();
215 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
216 #ifndef HAVE_COREAUDIO
217 /* if we have CoreAudio, we will be falling back to that if libsndfile fails,
218 so we don't want to see this message.
221 cerr << "failed to open " << _path << " with name " << _name << endl;
223 error << string_compose(_("SndFileSource: cannot open file \"%1\" for %2 (%3)"),
224 _path, (writable() ? "read+write" : "reading"), errbuf) << endmsg;
229 if (_channel >= _info.channels) {
230 #ifndef HAVE_COREAUDIO
231 error << string_compose(_("SndFileSource: file only contains %1 channels; %2 is invalid as a channel number"), _info.channels, _channel) << endmsg;
238 _length = _info.frames;
240 if (!_broadcast_info) {
241 _broadcast_info = new BroadcastInfo;
244 bool bwf_info_exists = _broadcast_info->load_from_file (sf);
246 set_timeline_position (bwf_info_exists ? _broadcast_info->get_time_reference() : header_position_offset);
248 if (_length != 0 && !bwf_info_exists) {
249 delete _broadcast_info;
251 _flags = Flag (_flags & ~Broadcast);
255 sf_command (sf, SFC_SET_UPDATE_HEADER_AUTO, 0, SF_FALSE);
258 _descriptor->release ();
262 SndFileSource::~SndFileSource ()
265 delete _broadcast_info;
270 SndFileSource::sample_rate () const
272 return _info.samplerate;
276 SndFileSource::read_unlocked (Sample *dst, framepos_t start, framecnt_t cnt) const
283 SNDFILE* sf = _descriptor->allocate ();
285 error << string_compose (_("could not allocate file %1 for reading."), _path) << endmsg;
289 if (start > _length) {
291 /* read starts beyond end of data, just memset to zero */
295 } else if (start + cnt > _length) {
297 /* read ends beyond end of data, read some, memset the rest */
299 file_cnt = _length - start;
303 /* read is entirely within data */
308 if (file_cnt != cnt) {
309 framepos_t delta = cnt - file_cnt;
310 memset (dst+file_cnt, 0, sizeof (Sample) * delta);
315 if (sf_seek (sf, (sf_count_t) start, SEEK_SET|SFM_READ) != (sf_count_t) start) {
317 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
318 error << string_compose(_("SndFileSource: could not seek to frame %1 within %2 (%3)"), start, _name.val().substr (1), errbuf) << endmsg;
319 _descriptor->release ();
323 if (_info.channels == 1) {
324 nframes_t ret = sf_read_float (sf, dst, file_cnt);
325 _read_data_count = ret * sizeof(float);
326 if (ret != file_cnt) {
328 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
329 error << string_compose(_("SndFileSource: @ %1 could not read %2 within %3 (%4) (len = %5)"), start, file_cnt, _name.val().substr (1), errbuf, _length) << endl;
331 _descriptor->release ();
336 real_cnt = cnt * _info.channels;
338 Sample* interleave_buf = get_interleave_buffer (real_cnt);
340 nread = sf_read_float (sf, interleave_buf, real_cnt);
341 ptr = interleave_buf + _channel;
342 nread /= _info.channels;
344 /* stride through the interleaved data */
346 for (int32_t n = 0; n < nread; ++n) {
348 ptr += _info.channels;
351 _read_data_count = cnt * sizeof(float);
353 _descriptor->release ();
358 SndFileSource::write_unlocked (Sample *data, framecnt_t cnt)
361 return destructive_write_unlocked (data, cnt);
363 return nondestructive_write_unlocked (data, cnt);
368 SndFileSource::nondestructive_write_unlocked (Sample *data, framecnt_t cnt)
371 warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
375 if (_info.channels != 1) {
376 fatal << string_compose (_("programming error: %1 %2"), X_("SndFileSource::write called on non-mono file"), _path) << endmsg;
382 int32_t frame_pos = _length;
384 if (write_float (data, frame_pos, cnt) != cnt) {
389 update_length (oldlen, cnt);
391 if (_build_peakfiles) {
392 compute_and_write_peaks (data, frame_pos, cnt, false, true);
395 _write_data_count = cnt;
401 SndFileSource::destructive_write_unlocked (Sample* data, framecnt_t cnt)
403 framepos_t old_file_pos;
406 warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
410 if (_capture_start && _capture_end) {
412 /* start and end of capture both occur within the data we are writing,
413 so do both crossfades.
416 _capture_start = false;
417 _capture_end = false;
419 /* move to the correct location place */
420 file_pos = capture_start_frame - _timeline_position;
423 nframes_t subcnt = cnt / 2;
424 nframes_t ofilepos = file_pos;
427 if (crossfade (data, subcnt, 1) != subcnt) {
432 Sample * tmpdata = data + subcnt;
435 subcnt = cnt - subcnt;
436 if (crossfade (tmpdata, subcnt, 0) != subcnt) {
440 file_pos = ofilepos; // adjusted below
442 } else if (_capture_start) {
444 /* start of capture both occur within the data we are writing,
448 _capture_start = false;
449 _capture_end = false;
451 /* move to the correct location place */
452 file_pos = capture_start_frame - _timeline_position;
454 if (crossfade (data, cnt, 1) != cnt) {
458 } else if (_capture_end) {
460 /* end of capture both occur within the data we are writing,
464 _capture_start = false;
465 _capture_end = false;
467 if (crossfade (data, cnt, 0) != cnt) {
473 /* in the middle of recording */
475 if (write_float (data, file_pos, cnt) != cnt) {
480 old_file_pos = file_pos;
481 update_length (file_pos, cnt);
483 if (_build_peakfiles) {
484 compute_and_write_peaks (data, file_pos, cnt, false, true);
493 SndFileSource::update_header (framepos_t when, struct tm& now, time_t tnow)
495 set_timeline_position (when);
497 if (_flags & Broadcast) {
498 if (setup_broadcast_info (when, now, tnow)) {
503 return flush_header ();
507 SndFileSource::flush_header ()
510 warning << string_compose (_("attempt to flush a non-writable audio file source (%1)"), _path) << endmsg;
514 SNDFILE* sf = _descriptor->allocate ();
516 error << string_compose (_("could not allocate file %1 to write header"), _path) << endmsg;
520 int const r = sf_command (sf, SFC_UPDATE_HEADER_NOW, 0, 0) != SF_TRUE;
521 _descriptor->release ();
527 SndFileSource::setup_broadcast_info (framepos_t /*when*/, struct tm& now, time_t /*tnow*/)
530 warning << string_compose (_("attempt to store broadcast info in a non-writable audio file source (%1)"), _path) << endmsg;
534 if (!(_flags & Broadcast)) {
538 _broadcast_info->set_originator_ref_from_session (_session);
539 _broadcast_info->set_origination_time (&now);
541 /* now update header position taking header offset into account */
543 set_header_timeline_position ();
545 SNDFILE* sf = _descriptor->allocate ();
547 if (sf == 0 || !_broadcast_info->write_to_file (sf)) {
548 error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"),
549 _path, _broadcast_info->get_error())
551 _flags = Flag (_flags & ~Broadcast);
552 delete _broadcast_info;
556 _descriptor->release ();
561 SndFileSource::set_header_timeline_position ()
563 if (!(_flags & Broadcast)) {
567 _broadcast_info->set_time_reference (_timeline_position);
569 SNDFILE* sf = _descriptor->allocate ();
571 if (sf == 0 || !_broadcast_info->write_to_file (sf)) {
572 error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"),
573 _path, _broadcast_info->get_error())
575 _flags = Flag (_flags & ~Broadcast);
576 delete _broadcast_info;
580 _descriptor->release ();
584 SndFileSource::write_float (Sample* data, framepos_t frame_pos, framecnt_t cnt)
586 SNDFILE* sf = _descriptor->allocate ();
588 if (sf == 0 || sf_seek (sf, frame_pos, SEEK_SET|SFM_WRITE) < 0) {
590 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
591 error << string_compose (_("%1: cannot seek to %2 (libsndfile error: %3"), _path, frame_pos, errbuf) << endmsg;
592 _descriptor->release ();
596 if (sf_writef_float (sf, data, cnt) != (ssize_t) cnt) {
597 _descriptor->release ();
601 _descriptor->release ();
606 SndFileSource::natural_position() const
608 return _timeline_position;
612 SndFileSource::set_destructive (bool yn)
615 _flags = Flag (_flags | Destructive);
617 xfade_buf = new Sample[xfade_frames];
619 clear_capture_marks ();
620 _timeline_position = header_position_offset;
622 _flags = Flag (_flags & ~Destructive);
623 _timeline_position = 0;
624 /* leave xfade buf alone in case we need it again later */
631 SndFileSource::clear_capture_marks ()
633 _capture_start = false;
634 _capture_end = false;
637 /** @param pos Capture start position in session frames */
639 SndFileSource::mark_capture_start (framepos_t pos)
642 if (pos < _timeline_position) {
643 _capture_start = false;
645 _capture_start = true;
646 capture_start_frame = pos;
652 SndFileSource::mark_capture_end()
660 SndFileSource::crossfade (Sample* data, framecnt_t cnt, int fade_in)
662 framecnt_t xfade = min (xfade_frames, cnt);
663 framecnt_t nofade = cnt - xfade;
664 Sample* fade_data = 0;
665 framepos_t fade_position = 0; // in frames
670 fade_position = file_pos;
673 fade_position = file_pos + nofade;
674 fade_data = data + nofade;
677 if (fade_position > _length) {
679 /* read starts beyond end of data, just memset to zero */
683 } else if (fade_position + xfade > _length) {
685 /* read ends beyond end of data, read some, memset the rest */
687 file_cnt = _length - fade_position;
691 /* read is entirely within data */
698 if ((retval = read_unlocked (xfade_buf, fade_position, file_cnt)) != (ssize_t) file_cnt) {
699 if (retval >= 0 && errno == EAGAIN) {
700 /* XXX - can we really trust that errno is meaningful here? yes POSIX, i'm talking to you.
701 * short or no data there */
702 memset (xfade_buf, 0, xfade * sizeof(Sample));
704 error << string_compose(_("SndFileSource: \"%1\" bad read retval: %2 of %5 (%3: %4)"), _path, retval, errno, strerror (errno), xfade) << endmsg;
710 if (file_cnt != xfade) {
711 framecnt_t delta = xfade - file_cnt;
712 memset (xfade_buf+file_cnt, 0, sizeof (Sample) * delta);
715 if (nofade && !fade_in) {
716 if (write_float (data, file_pos, nofade) != nofade) {
717 error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
722 if (xfade == xfade_frames) {
726 /* use the standard xfade curve */
730 /* fade new material in */
732 for (n = 0; n < xfade; ++n) {
733 xfade_buf[n] = (xfade_buf[n] * out_coefficient[n]) + (fade_data[n] * in_coefficient[n]);
739 /* fade new material out */
741 for (n = 0; n < xfade; ++n) {
742 xfade_buf[n] = (xfade_buf[n] * in_coefficient[n]) + (fade_data[n] * out_coefficient[n]);
746 } else if (xfade < xfade_frames) {
751 /* short xfade, compute custom curve */
753 compute_equal_power_fades (xfade, in, out);
755 for (framecnt_t n = 0; n < xfade; ++n) {
756 xfade_buf[n] = (xfade_buf[n] * out[n]) + (fade_data[n] * in[n]);
761 /* long xfade length, has to be computed across several calls */
766 if (write_float (xfade_buf, fade_position, xfade) != xfade) {
767 error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
772 if (fade_in && nofade) {
773 if (write_float (data + xfade, file_pos + xfade, nofade) != nofade) {
774 error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
783 SndFileSource::last_capture_start_frame () const
786 return capture_start_frame;
793 SndFileSource::handle_header_position_change ()
796 if ( _length != 0 ) {
797 error << string_compose(_("Filesource: start time is already set for existing file (%1): Cannot change start time."), _path ) << endmsg;
798 //in the future, pop up a dialog here that allows user to regenerate file with new start offset
799 } else if (writable()) {
800 _timeline_position = header_position_offset;
801 set_header_timeline_position (); //this will get flushed if/when the file is recorded to
807 SndFileSource::setup_standard_crossfades (Session const & s, nframes_t rate)
809 /* This static method is assumed to have been called by the Session
810 before any DFS's are created.
813 xfade_frames = (framecnt_t) floor ((s.config.get_destructive_xfade_msecs () / 1000.0) * rate);
815 delete [] out_coefficient;
816 delete [] in_coefficient;
818 out_coefficient = new gain_t[xfade_frames];
819 in_coefficient = new gain_t[xfade_frames];
821 compute_equal_power_fades (xfade_frames, in_coefficient, out_coefficient);
825 SndFileSource::set_timeline_position (framepos_t pos)
827 // destructive track timeline postion does not change
828 // except at instantion or when header_position_offset
829 // (session start) changes
831 if (!destructive()) {
832 AudioFileSource::set_timeline_position (pos);
837 SndFileSource::get_soundfile_info (const string& path, SoundFileInfo& info, string& error_msg)
843 sf_info.format = 0; // libsndfile says to clear this before sf_open().
845 if ((sf = sf_open ((char*) path.c_str(), SFM_READ, &sf_info)) == 0) {
847 error_msg = sf_error_str (0, errbuf, sizeof (errbuf) - 1);
851 info.samplerate = sf_info.samplerate;
852 info.channels = sf_info.channels;
853 info.length = sf_info.frames;
855 string major = sndfile_major_format(sf_info.format);
856 string minor = sndfile_minor_format(sf_info.format);
858 if (major.length() + minor.length() < 16) { /* arbitrary */
859 info.format_name = string_compose("%1/%2", major, minor);
861 info.format_name = string_compose("%1\n%2", major, minor);
864 info.timecode = binfo.load_from_file (sf) ? binfo.get_time_reference() : 0;
872 SndFileSource::one_of_several_channels () const
874 return _info.channels > 1;
878 SndFileSource::clamped_at_unity () const
880 int const sub = _info.format & SF_FORMAT_SUBMASK;
881 /* XXX: this may not be the full list of formats that are unclamped */
882 return (sub != SF_FORMAT_FLOAT && sub != SF_FORMAT_DOUBLE);
886 SndFileSource::file_closed ()
888 /* stupid libsndfile updated the headers on close,
889 so touch the peakfile if it exists and has data
890 to make sure its time is as new as the audio
898 SndFileSource::set_path (const string& p)
900 FileSource::set_path (p);
903 _descriptor->set_path (_path);