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 , AudioFileSource (s, path, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
79 throw failed_constructor ();
83 /** This constructor is used to construct new files, not open existing ones. */
84 SndFileSource::SndFileSource (Session& s, const string& path,
85 SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
86 : Source(s, DataType::AUDIO, path, flags)
87 , AudioFileSource (s, path, flags, sfmt, hf)
98 _flags = Flag (_flags & ~Broadcast);
102 fmt = SF_FORMAT_AIFF;
103 _flags = Flag (_flags & ~Broadcast);
108 _flags = Flag (_flags | Broadcast);
113 _flags = Flag (_flags & ~Broadcast);
118 _flags = Flag (_flags & ~Broadcast);
122 fatal << string_compose (_("programming error: %1"), X_("unsupported audio header format requested")) << endmsg;
130 fmt |= SF_FORMAT_FLOAT;
134 fmt |= SF_FORMAT_PCM_24;
138 fmt |= SF_FORMAT_PCM_16;
143 _info.samplerate = rate;
147 throw failed_constructor();
150 if (writable() && (_flags & Broadcast)) {
152 SNDFILE* sf = _descriptor->allocate ();
154 error << string_compose (_("could not allocate file %1"), _path) << endmsg;
155 throw failed_constructor ();
158 if (!_broadcast_info) {
159 _broadcast_info = new BroadcastInfo;
162 _broadcast_info->set_from_session (s, header_position_offset);
163 _broadcast_info->set_description (string_compose ("BWF %1", _name));
165 if (!_broadcast_info->write_to_file (sf)) {
166 error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"),
167 _path, _broadcast_info->get_error())
169 _flags = Flag (_flags & ~Broadcast);
170 delete _broadcast_info;
174 _descriptor->release ();
179 SndFileSource::init_sndfile ()
183 // lets try to keep the object initalizations here at the top
187 /* although libsndfile says we don't need to set this,
188 valgrind and source code shows us that we do.
191 memset (&_info, 0, sizeof(_info));
193 _capture_start = false;
194 _capture_end = false;
198 xfade_buf = new Sample[xfade_frames];
199 _timeline_position = header_position_offset;
202 AudioFileSource::HeaderPositionOffsetChanged.connect_same_thread (header_position_connection, boost::bind (&SndFileSource::handle_header_position_change, this));
206 SndFileSource::open ()
208 _descriptor = new SndFileDescriptor (_path, writable(), &_info);
209 _descriptor->Closed.connect_same_thread (file_manager_connection, boost::bind (&SndFileSource::file_closed, this));
210 SNDFILE* sf = _descriptor->allocate ();
214 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
215 #ifndef HAVE_COREAUDIO
216 /* if we have CoreAudio, we will be falling back to that if libsndfile fails,
217 so we don't want to see this message.
220 error << string_compose(_("SndFileSource: cannot open file \"%1\" for %2 (%3)"),
221 _path, (writable() ? "read+write" : "reading"), errbuf) << endmsg;
226 if (_channel >= _info.channels) {
227 #ifndef HAVE_COREAUDIO
228 error << string_compose(_("SndFileSource: file only contains %1 channels; %2 is invalid as a channel number"), _info.channels, _channel) << endmsg;
235 _length = _info.frames;
237 if (!_broadcast_info) {
238 _broadcast_info = new BroadcastInfo;
241 bool bwf_info_exists = _broadcast_info->load_from_file (sf);
243 set_timeline_position (bwf_info_exists ? _broadcast_info->get_time_reference() : header_position_offset);
245 if (_length != 0 && !bwf_info_exists) {
246 delete _broadcast_info;
248 _flags = Flag (_flags & ~Broadcast);
252 sf_command (sf, SFC_SET_UPDATE_HEADER_AUTO, 0, SF_FALSE);
255 _descriptor->release ();
259 SndFileSource::~SndFileSource ()
262 delete _broadcast_info;
267 SndFileSource::sample_rate () const
269 return _info.samplerate;
273 SndFileSource::read_unlocked (Sample *dst, framepos_t start, framecnt_t cnt) const
280 SNDFILE* sf = _descriptor->allocate ();
282 error << string_compose (_("could not allocate file %1 for reading."), _path) << endmsg;
286 if (start > _length) {
288 /* read starts beyond end of data, just memset to zero */
292 } else if (start + cnt > _length) {
294 /* read ends beyond end of data, read some, memset the rest */
296 file_cnt = _length - start;
300 /* read is entirely within data */
305 if (file_cnt != cnt) {
306 framepos_t delta = cnt - file_cnt;
307 memset (dst+file_cnt, 0, sizeof (Sample) * delta);
312 if (sf_seek (sf, (sf_count_t) start, SEEK_SET|SFM_READ) != (sf_count_t) start) {
314 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
315 error << string_compose(_("SndFileSource: could not seek to frame %1 within %2 (%3)"), start, _name.val().substr (1), errbuf) << endmsg;
316 _descriptor->release ();
320 if (_info.channels == 1) {
321 nframes_t ret = sf_read_float (sf, dst, file_cnt);
322 _read_data_count = ret * sizeof(float);
323 if (ret != file_cnt) {
325 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
326 error << string_compose(_("SndFileSource: @ %1 could not read %2 within %3 (%4) (len = %5)"), start, file_cnt, _name.val().substr (1), errbuf, _length) << endl;
328 _descriptor->release ();
333 real_cnt = cnt * _info.channels;
335 Sample* interleave_buf = get_interleave_buffer (real_cnt);
337 nread = sf_read_float (sf, interleave_buf, real_cnt);
338 ptr = interleave_buf + _channel;
339 nread /= _info.channels;
341 /* stride through the interleaved data */
343 for (int32_t n = 0; n < nread; ++n) {
345 ptr += _info.channels;
348 _read_data_count = cnt * sizeof(float);
350 _descriptor->release ();
355 SndFileSource::write_unlocked (Sample *data, framecnt_t cnt)
358 return destructive_write_unlocked (data, cnt);
360 return nondestructive_write_unlocked (data, cnt);
365 SndFileSource::nondestructive_write_unlocked (Sample *data, framecnt_t cnt)
368 warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
372 if (_info.channels != 1) {
373 fatal << string_compose (_("programming error: %1 %2"), X_("SndFileSource::write called on non-mono file"), _path) << endmsg;
379 int32_t frame_pos = _length;
381 if (write_float (data, frame_pos, cnt) != cnt) {
386 update_length (oldlen, cnt);
388 if (_build_peakfiles) {
389 compute_and_write_peaks (data, frame_pos, cnt, false, true);
392 _write_data_count = cnt;
398 SndFileSource::destructive_write_unlocked (Sample* data, framecnt_t cnt)
400 framepos_t old_file_pos;
403 warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
407 if (_capture_start && _capture_end) {
409 /* start and end of capture both occur within the data we are writing,
410 so do both crossfades.
413 _capture_start = false;
414 _capture_end = false;
416 /* move to the correct location place */
417 file_pos = capture_start_frame - _timeline_position;
420 nframes_t subcnt = cnt / 2;
421 nframes_t ofilepos = file_pos;
424 if (crossfade (data, subcnt, 1) != subcnt) {
429 Sample * tmpdata = data + subcnt;
432 subcnt = cnt - subcnt;
433 if (crossfade (tmpdata, subcnt, 0) != subcnt) {
437 file_pos = ofilepos; // adjusted below
439 } else if (_capture_start) {
441 /* start of capture both occur within the data we are writing,
445 _capture_start = false;
446 _capture_end = false;
448 /* move to the correct location place */
449 file_pos = capture_start_frame - _timeline_position;
451 if (crossfade (data, cnt, 1) != cnt) {
455 } else if (_capture_end) {
457 /* end of capture both occur within the data we are writing,
461 _capture_start = false;
462 _capture_end = false;
464 if (crossfade (data, cnt, 0) != cnt) {
470 /* in the middle of recording */
472 if (write_float (data, file_pos, cnt) != cnt) {
477 old_file_pos = file_pos;
478 update_length (file_pos, cnt);
480 if (_build_peakfiles) {
481 compute_and_write_peaks (data, file_pos, cnt, false, true);
490 SndFileSource::update_header (sframes_t when, struct tm& now, time_t tnow)
492 set_timeline_position (when);
494 if (_flags & Broadcast) {
495 if (setup_broadcast_info (when, now, tnow)) {
500 return flush_header ();
504 SndFileSource::flush_header ()
507 warning << string_compose (_("attempt to flush a non-writable audio file source (%1)"), _path) << endmsg;
511 SNDFILE* sf = _descriptor->allocate ();
513 error << string_compose (_("could not allocate file %1 to write header"), _path) << endmsg;
517 int const r = sf_command (sf, SFC_UPDATE_HEADER_NOW, 0, 0) != SF_TRUE;
518 _descriptor->release ();
524 SndFileSource::setup_broadcast_info (sframes_t /*when*/, struct tm& now, time_t /*tnow*/)
527 warning << string_compose (_("attempt to store broadcast info in a non-writable audio file source (%1)"), _path) << endmsg;
531 if (!(_flags & Broadcast)) {
535 _broadcast_info->set_originator_ref_from_session (_session);
536 _broadcast_info->set_origination_time (&now);
538 /* now update header position taking header offset into account */
540 set_header_timeline_position ();
542 SNDFILE* sf = _descriptor->allocate ();
544 if (sf == 0 || !_broadcast_info->write_to_file (sf)) {
545 error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"),
546 _path, _broadcast_info->get_error())
548 _flags = Flag (_flags & ~Broadcast);
549 delete _broadcast_info;
553 _descriptor->release ();
558 SndFileSource::set_header_timeline_position ()
560 if (!(_flags & Broadcast)) {
564 _broadcast_info->set_time_reference (_timeline_position);
566 SNDFILE* sf = _descriptor->allocate ();
568 if (sf == 0 || !_broadcast_info->write_to_file (sf)) {
569 error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"),
570 _path, _broadcast_info->get_error())
572 _flags = Flag (_flags & ~Broadcast);
573 delete _broadcast_info;
577 _descriptor->release ();
581 SndFileSource::write_float (Sample* data, framepos_t frame_pos, framecnt_t cnt)
583 SNDFILE* sf = _descriptor->allocate ();
585 if (sf == 0 || sf_seek (sf, frame_pos, SEEK_SET|SFM_WRITE) < 0) {
587 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
588 error << string_compose (_("%1: cannot seek to %2 (libsndfile error: %3"), _path, frame_pos, errbuf) << endmsg;
589 _descriptor->release ();
593 if (sf_writef_float (sf, data, cnt) != (ssize_t) cnt) {
594 _descriptor->release ();
598 _descriptor->release ();
603 SndFileSource::natural_position() const
605 return _timeline_position;
609 SndFileSource::set_destructive (bool yn)
612 _flags = Flag (_flags | Destructive);
614 xfade_buf = new Sample[xfade_frames];
616 clear_capture_marks ();
617 _timeline_position = header_position_offset;
619 _flags = Flag (_flags & ~Destructive);
620 _timeline_position = 0;
621 /* leave xfade buf alone in case we need it again later */
628 SndFileSource::clear_capture_marks ()
630 _capture_start = false;
631 _capture_end = false;
635 SndFileSource::mark_capture_start (sframes_t pos)
638 if (pos < _timeline_position) {
639 _capture_start = false;
641 _capture_start = true;
642 capture_start_frame = pos;
648 SndFileSource::mark_capture_end()
656 SndFileSource::crossfade (Sample* data, framecnt_t cnt, int fade_in)
658 framecnt_t xfade = min (xfade_frames, cnt);
659 framecnt_t nofade = cnt - xfade;
660 Sample* fade_data = 0;
661 framepos_t fade_position = 0; // in frames
666 fade_position = file_pos;
669 fade_position = file_pos + nofade;
670 fade_data = data + nofade;
673 if (fade_position > _length) {
675 /* read starts beyond end of data, just memset to zero */
679 } else if (fade_position + xfade > _length) {
681 /* read ends beyond end of data, read some, memset the rest */
683 file_cnt = _length - fade_position;
687 /* read is entirely within data */
694 if ((retval = read_unlocked (xfade_buf, fade_position, file_cnt)) != (ssize_t) file_cnt) {
695 if (retval >= 0 && errno == EAGAIN) {
696 /* XXX - can we really trust that errno is meaningful here? yes POSIX, i'm talking to you.
697 * short or no data there */
698 memset (xfade_buf, 0, xfade * sizeof(Sample));
700 error << string_compose(_("SndFileSource: \"%1\" bad read retval: %2 of %5 (%3: %4)"), _path, retval, errno, strerror (errno), xfade) << endmsg;
706 if (file_cnt != xfade) {
707 framecnt_t delta = xfade - file_cnt;
708 memset (xfade_buf+file_cnt, 0, sizeof (Sample) * delta);
711 if (nofade && !fade_in) {
712 if (write_float (data, file_pos, nofade) != nofade) {
713 error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
718 if (xfade == xfade_frames) {
722 /* use the standard xfade curve */
726 /* fade new material in */
728 for (n = 0; n < xfade; ++n) {
729 xfade_buf[n] = (xfade_buf[n] * out_coefficient[n]) + (fade_data[n] * in_coefficient[n]);
735 /* fade new material out */
737 for (n = 0; n < xfade; ++n) {
738 xfade_buf[n] = (xfade_buf[n] * in_coefficient[n]) + (fade_data[n] * out_coefficient[n]);
742 } else if (xfade < xfade_frames) {
747 /* short xfade, compute custom curve */
749 compute_equal_power_fades (xfade, in, out);
751 for (framecnt_t n = 0; n < xfade; ++n) {
752 xfade_buf[n] = (xfade_buf[n] * out[n]) + (fade_data[n] * in[n]);
757 /* long xfade length, has to be computed across several calls */
762 if (write_float (xfade_buf, fade_position, xfade) != xfade) {
763 error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
768 if (fade_in && nofade) {
769 if (write_float (data + xfade, file_pos + xfade, nofade) != nofade) {
770 error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
779 SndFileSource::last_capture_start_frame () const
782 return capture_start_frame;
789 SndFileSource::handle_header_position_change ()
792 if ( _length != 0 ) {
793 error << string_compose(_("Filesource: start time is already set for existing file (%1): Cannot change start time."), _path ) << endmsg;
794 //in the future, pop up a dialog here that allows user to regenerate file with new start offset
795 } else if (writable()) {
796 _timeline_position = header_position_offset;
797 set_header_timeline_position (); //this will get flushed if/when the file is recorded to
803 SndFileSource::setup_standard_crossfades (Session const & s, nframes_t rate)
805 /* This static method is assumed to have been called by the Session
806 before any DFS's are created.
809 xfade_frames = (framecnt_t) floor ((s.config.get_destructive_xfade_msecs () / 1000.0) * rate);
811 delete [] out_coefficient;
812 delete [] in_coefficient;
814 out_coefficient = new gain_t[xfade_frames];
815 in_coefficient = new gain_t[xfade_frames];
817 compute_equal_power_fades (xfade_frames, in_coefficient, out_coefficient);
821 SndFileSource::set_timeline_position (int64_t pos)
823 // destructive track timeline postion does not change
824 // except at instantion or when header_position_offset
825 // (session start) changes
827 if (!destructive()) {
828 AudioFileSource::set_timeline_position (pos);
833 SndFileSource::get_soundfile_info (const string& path, SoundFileInfo& info, string& error_msg)
839 sf_info.format = 0; // libsndfile says to clear this before sf_open().
841 if ((sf = sf_open ((char*) path.c_str(), SFM_READ, &sf_info)) == 0) {
843 error_msg = sf_error_str (0, errbuf, sizeof (errbuf) - 1);
847 info.samplerate = sf_info.samplerate;
848 info.channels = sf_info.channels;
849 info.length = sf_info.frames;
851 string major = sndfile_major_format(sf_info.format);
852 string minor = sndfile_minor_format(sf_info.format);
854 if (major.length() + minor.length() < 16) { /* arbitrary */
855 info.format_name = string_compose("%1/%2", major, minor);
857 info.format_name = string_compose("%1\n%2", major, minor);
860 info.timecode = binfo.load_from_file (sf) ? binfo.get_time_reference() : 0;
868 SndFileSource::one_of_several_channels () const
870 return _info.channels > 1;
874 SndFileSource::clamped_at_unity () const
876 int const sub = _info.format & SF_FORMAT_SUBMASK;
877 /* XXX: this may not be the full list of formats that are unclamped */
878 return (sub != SF_FORMAT_FLOAT && sub != SF_FORMAT_DOUBLE);
882 SndFileSource::file_closed ()
884 /* stupid libsndfile updated the headers on close,
885 so touch the peakfile if it exists and has data
886 to make sure its time is as new as the audio
894 SndFileSource::set_path (const string& p)
896 FileSource::set_path (p);
899 _descriptor->set_path (_path);