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.
25 #include <sys/utsname.h>
28 #include <glibmm/miscutils.h>
30 #include <ardour/sndfilesource.h>
31 #include <ardour/sndfile_helpers.h>
32 #include <ardour/utils.h>
37 using namespace ARDOUR;
40 gain_t* SndFileSource::out_coefficient = 0;
41 gain_t* SndFileSource::in_coefficient = 0;
42 nframes_t SndFileSource::xfade_frames = 64;
43 const AudioFileSource::Flag SndFileSource::default_writable_flags = AudioFileSource::Flag (AudioFileSource::Writable|
44 AudioFileSource::Removable|
45 AudioFileSource::RemovableIfEmpty|
46 AudioFileSource::CanRename);
48 SndFileSource::SndFileSource (Session& s, const XMLNode& node)
49 : AudioFileSource (s, node)
54 throw failed_constructor ();
58 SndFileSource::SndFileSource (Session& s, string idstr, Flag flags)
59 /* files created this way are never writable or removable */
60 : AudioFileSource (s, idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
65 throw failed_constructor ();
69 SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
70 : AudioFileSource (s, idstr, flags, sfmt, hf)
76 /* this constructor is used to construct new files, not open
85 _flags = Flag (_flags & ~Broadcast);
90 _flags = Flag (_flags & ~Broadcast);
95 _flags = Flag (_flags | Broadcast);
100 _flags = Flag (_flags & ~Broadcast);
105 _flags = Flag (_flags & ~Broadcast);
109 fatal << string_compose (_("programming error: %1"), X_("unsupported audio header format requested")) << endmsg;
117 fmt |= SF_FORMAT_FLOAT;
121 fmt |= SF_FORMAT_PCM_24;
126 _info.samplerate = rate;
130 throw failed_constructor();
133 if (writable() && (_flags & Broadcast)) {
135 _broadcast_info = new SF_BROADCAST_INFO;
136 memset (_broadcast_info, 0, sizeof (*_broadcast_info));
138 snprintf (_broadcast_info->description, sizeof (_broadcast_info->description), "BWF %s", _name.c_str());
140 struct utsname utsinfo;
142 if (uname (&utsinfo)) {
143 error << string_compose(_("FileSource: cannot get host information for BWF header (%1)"), strerror(errno)) << endmsg;
147 snprintf (_broadcast_info->originator, sizeof (_broadcast_info->originator), "ardour:%s:%s:%s:%s:%s)",
148 Glib::get_real_name().c_str(),
154 _broadcast_info->version = 1;
155 _broadcast_info->time_reference_low = 0;
156 _broadcast_info->time_reference_high = 0;
158 /* XXX do something about this field */
160 snprintf (_broadcast_info->umid, sizeof (_broadcast_info->umid), "%s", "fnord");
162 /* coding history is added by libsndfile */
164 if (sf_command (sf, SFC_SET_BROADCAST_INFO, _broadcast_info, sizeof (_broadcast_info)) != SF_TRUE) {
166 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
167 error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"), _path, errbuf) << endmsg;
168 _flags = Flag (_flags & ~Broadcast);
169 delete _broadcast_info;
177 SndFileSource::init (string idstr)
179 string::size_type pos;
182 // lets try to keep the object initalizations here at the top
185 interleave_bufsize = 0;
191 if ((pos = idstr.find_last_of (':')) == string::npos) {
195 channel = atoi (idstr.substr (pos+1).c_str());
196 tmp_name = idstr.substr (0, pos);
202 _name = Glib::path_get_basename (tmp_name);
205 /* although libsndfile says we don't need to set this,
206 valgrind and source code shows us that we do.
209 memset (&_info, 0, sizeof(_info));
211 _capture_start = false;
212 _capture_end = false;
216 xfade_buf = new Sample[xfade_frames];
217 timeline_position = header_position_offset;
220 AudioFileSource::HeaderPositionOffsetChanged.connect (mem_fun (*this, &SndFileSource::handle_header_position_change));
224 SndFileSource::open ()
226 if ((sf = sf_open (_path.c_str(), (writable() ? SFM_RDWR : SFM_READ), &_info)) == 0) {
228 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
229 error << string_compose(_("SndFileSource: cannot open file \"%1\" for %2 (%3)"),
230 _path, (writable() ? "read+write" : "reading"), errbuf) << endmsg;
234 if (channel >= _info.channels) {
235 error << string_compose(_("SndFileSource: file only contains %1 channels; %2 is invalid as a channel number"), _info.channels, channel) << endmsg;
241 _length = _info.frames;
243 _broadcast_info = new SF_BROADCAST_INFO;
244 memset (_broadcast_info, 0, sizeof (*_broadcast_info));
246 bool timecode_info_exists;
248 set_timeline_position (get_timecode_info (sf, _broadcast_info, timecode_info_exists));
250 if (!timecode_info_exists) {
251 delete _broadcast_info;
253 _flags = Flag (_flags & ~Broadcast);
257 sf_command (sf, SFC_SET_UPDATE_HEADER_AUTO, 0, SF_FALSE);
263 SndFileSource::~SndFileSource ()
265 GoingAway (); /* EMIT SIGNAL */
271 /* stupid libsndfile updated the headers on close,
272 so touch the peakfile if it exists and has data
273 to make sure its time is as new as the audio
280 if (interleave_buf) {
281 delete [] interleave_buf;
284 if (_broadcast_info) {
285 delete _broadcast_info;
294 SndFileSource::sample_rate () const
296 return _info.samplerate;
300 SndFileSource::read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const
307 if (start > _length) {
309 /* read starts beyond end of data, just memset to zero */
313 } else if (start + cnt > _length) {
315 /* read ends beyond end of data, read some, memset the rest */
317 file_cnt = _length - start;
321 /* read is entirely within data */
328 if (sf_seek (sf, (sf_count_t) start, SEEK_SET|SFM_READ) != (sf_count_t) start) {
330 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
331 error << string_compose(_("SndFileSource: could not seek to frame %1 within %2 (%3)"), start, _name.substr (1), errbuf) << endmsg;
335 if (_info.channels == 1) {
336 nframes_t ret = sf_read_float (sf, dst, file_cnt);
337 _read_data_count = cnt * sizeof(float);
342 if (file_cnt != cnt) {
343 nframes_t delta = cnt - file_cnt;
344 memset (dst+file_cnt, 0, sizeof (Sample) * delta);
347 real_cnt = cnt * _info.channels;
349 if (interleave_bufsize < real_cnt) {
351 if (interleave_buf) {
352 delete [] interleave_buf;
354 interleave_bufsize = real_cnt;
355 interleave_buf = new float[interleave_bufsize];
358 nread = sf_read_float (sf, interleave_buf, real_cnt);
359 ptr = interleave_buf + channel;
360 nread /= _info.channels;
362 /* stride through the interleaved data */
364 for (int32_t n = 0; n < nread; ++n) {
366 ptr += _info.channels;
369 _read_data_count = cnt * sizeof(float);
375 SndFileSource::write_unlocked (Sample *data, nframes_t cnt)
378 return destructive_write_unlocked (data, cnt);
380 return nondestructive_write_unlocked (data, cnt);
385 SndFileSource::nondestructive_write_unlocked (Sample *data, nframes_t cnt)
391 if (_info.channels != 1) {
392 fatal << string_compose (_("programming error: %1 %2"), X_("SndFileSource::write called on non-mono file"), _path) << endmsg;
398 int32_t frame_pos = _length;
400 if (write_float (data, frame_pos, cnt) != cnt) {
405 update_length (oldlen, cnt);
407 if (_build_peakfiles) {
408 PeakBuildRecord *pbr = 0;
410 if (pending_peak_builds.size()) {
411 pbr = pending_peak_builds.back();
414 if (pbr && pbr->frame + pbr->cnt == oldlen) {
416 /* the last PBR extended to the start of the current write,
417 so just extend it again.
421 pending_peak_builds.push_back (new PeakBuildRecord (oldlen, cnt));
424 _peaks_built = false;
428 if (_build_peakfiles) {
429 queue_for_peaks (shared_from_this (), false);
432 _write_data_count = cnt;
438 SndFileSource::destructive_write_unlocked (Sample* data, nframes_t cnt)
440 nframes_t old_file_pos;
446 if (_capture_start && _capture_end) {
448 /* start and end of capture both occur within the data we are writing,
449 so do both crossfades.
452 _capture_start = false;
453 _capture_end = false;
455 /* move to the correct location place */
456 file_pos = capture_start_frame - timeline_position;
459 nframes_t subcnt = cnt / 2;
460 nframes_t ofilepos = file_pos;
463 if (crossfade (data, subcnt, 1) != subcnt) {
468 Sample * tmpdata = data + subcnt;
471 subcnt = cnt - subcnt;
472 if (crossfade (tmpdata, subcnt, 0) != subcnt) {
476 file_pos = ofilepos; // adjusted below
478 } else if (_capture_start) {
480 /* start of capture both occur within the data we are writing,
484 _capture_start = false;
485 _capture_end = false;
487 /* move to the correct location place */
488 file_pos = capture_start_frame - timeline_position;
490 if (crossfade (data, cnt, 1) != cnt) {
494 } else if (_capture_end) {
496 /* end of capture both occur within the data we are writing,
500 _capture_start = false;
501 _capture_end = false;
503 if (crossfade (data, cnt, 0) != cnt) {
509 /* in the middle of recording */
511 if (write_float (data, file_pos, cnt) != cnt) {
516 old_file_pos = file_pos;
517 update_length (file_pos, cnt);
520 if (_build_peakfiles) {
521 PeakBuildRecord *pbr = 0;
523 if (pending_peak_builds.size()) {
524 pbr = pending_peak_builds.back();
527 if (pbr && pbr->frame + pbr->cnt == old_file_pos) {
529 /* the last PBR extended to the start of the current write,
530 so just extend it again.
535 pending_peak_builds.push_back (new PeakBuildRecord (old_file_pos, cnt));
538 _peaks_built = false;
541 if (_build_peakfiles) {
542 queue_for_peaks (shared_from_this (), true);
549 SndFileSource::update_header (nframes_t when, struct tm& now, time_t tnow)
551 set_timeline_position (when);
553 if (_flags & Broadcast) {
554 if (setup_broadcast_info (when, now, tnow)) {
559 return flush_header ();
563 SndFileSource::flush_header ()
565 if (!writable() || (sf == 0)) {
568 return (sf_command (sf, SFC_UPDATE_HEADER_NOW, 0, 0) != SF_TRUE);
572 SndFileSource::setup_broadcast_info (nframes_t when, struct tm& now, time_t tnow)
578 if (!(_flags & Broadcast)) {
582 /* random code is 9 digits */
584 int random_code = random() % 999999999;
586 snprintf (_broadcast_info->originator_reference, sizeof (_broadcast_info->originator_reference), "%2s%3s%12s%02d%02d%02d%9d",
587 Config->get_bwf_country_code().c_str(),
588 Config->get_bwf_organization_code().c_str(),
595 snprintf (_broadcast_info->origination_date, sizeof (_broadcast_info->origination_date), "%4d-%02d-%02d",
600 snprintf (_broadcast_info->origination_time, sizeof (_broadcast_info->origination_time), "%02d:%02d:%02d",
605 /* now update header position taking header offset into account */
607 set_header_timeline_position ();
609 if (sf_command (sf, SFC_SET_BROADCAST_INFO, _broadcast_info, sizeof (*_broadcast_info)) != SF_TRUE) {
610 error << string_compose (_("cannot set broadcast info for audio file %1; Dropping broadcast info for this file"), _path) << endmsg;
611 _flags = Flag (_flags & ~Broadcast);
612 delete _broadcast_info;
621 SndFileSource::set_header_timeline_position ()
623 if (!(_flags & Broadcast)) {
627 _broadcast_info->time_reference_high = (timeline_position >> 32);
628 _broadcast_info->time_reference_low = (timeline_position & 0xffffffff);
630 if (sf_command (sf, SFC_SET_BROADCAST_INFO, _broadcast_info, sizeof (*_broadcast_info)) != SF_TRUE) {
631 error << string_compose (_("cannot set broadcast info for audio file %1; Dropping broadcast info for this file"), _path) << endmsg;
632 _flags = Flag (_flags & ~Broadcast);
633 delete _broadcast_info;
642 SndFileSource::write_float (Sample* data, nframes_t frame_pos, nframes_t cnt)
644 if (sf_seek (sf, frame_pos, SEEK_SET|SFM_WRITE) < 0) {
646 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
647 error << string_compose (_("%1: cannot seek to %2 (libsndfile error: %3"), _path, frame_pos, errbuf) << endmsg;
651 if (sf_writef_float (sf, data, cnt) != (ssize_t) cnt) {
659 SndFileSource::natural_position() const
661 return timeline_position;
665 SndFileSource::set_destructive (bool yn)
668 _flags = Flag (_flags | Destructive);
670 xfade_buf = new Sample[xfade_frames];
672 clear_capture_marks ();
673 timeline_position = header_position_offset;
675 _flags = Flag (_flags & ~Destructive);
676 timeline_position = 0;
677 /* leave xfade buf alone in case we need it again later */
684 SndFileSource::clear_capture_marks ()
686 _capture_start = false;
687 _capture_end = false;
691 SndFileSource::mark_capture_start (nframes_t pos)
694 if (pos < timeline_position) {
695 _capture_start = false;
697 _capture_start = true;
698 capture_start_frame = pos;
704 SndFileSource::mark_capture_end()
712 SndFileSource::crossfade (Sample* data, nframes_t cnt, int fade_in)
714 nframes_t xfade = min (xfade_frames, cnt);
715 nframes_t nofade = cnt - xfade;
716 Sample* fade_data = 0;
717 nframes_t fade_position = 0; // in frames
722 fade_position = file_pos;
725 fade_position = file_pos + nofade;
726 fade_data = data + nofade;
729 if (fade_position > _length) {
731 /* read starts beyond end of data, just memset to zero */
735 } else if (fade_position + xfade > _length) {
737 /* read ends beyond end of data, read some, memset the rest */
739 file_cnt = _length - fade_position;
743 /* read is entirely within data */
750 if ((retval = read_unlocked (xfade_buf, fade_position, file_cnt)) != (ssize_t) file_cnt) {
751 if (retval >= 0 && errno == EAGAIN) {
752 /* XXX - can we really trust that errno is meaningful here? yes POSIX, i'm talking to you.
753 * short or no data there */
754 memset (xfade_buf, 0, xfade * sizeof(Sample));
756 error << string_compose(_("SndFileSource: \"%1\" bad read retval: %2 of %5 (%3: %4)"), _path, retval, errno, strerror (errno), xfade) << endmsg;
762 if (file_cnt != xfade) {
763 nframes_t delta = xfade - file_cnt;
764 memset (xfade_buf+file_cnt, 0, sizeof (Sample) * delta);
767 if (nofade && !fade_in) {
768 if (write_float (data, file_pos, nofade) != nofade) {
769 error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
774 if (xfade == xfade_frames) {
778 /* use the standard xfade curve */
782 /* fade new material in */
784 for (n = 0; n < xfade; ++n) {
785 xfade_buf[n] = (xfade_buf[n] * out_coefficient[n]) + (fade_data[n] * in_coefficient[n]);
791 /* fade new material out */
793 for (n = 0; n < xfade; ++n) {
794 xfade_buf[n] = (xfade_buf[n] * in_coefficient[n]) + (fade_data[n] * out_coefficient[n]);
798 } else if (xfade < xfade_frames) {
803 /* short xfade, compute custom curve */
805 compute_equal_power_fades (xfade, in, out);
807 for (nframes_t n = 0; n < xfade; ++n) {
808 xfade_buf[n] = (xfade_buf[n] * out[n]) + (fade_data[n] * in[n]);
813 /* long xfade length, has to be computed across several calls */
818 if (write_float (xfade_buf, fade_position, xfade) != xfade) {
819 error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
824 if (fade_in && nofade) {
825 if (write_float (data + xfade, file_pos + xfade, nofade) != nofade) {
826 error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
835 SndFileSource::last_capture_start_frame () const
838 return capture_start_frame;
845 SndFileSource::handle_header_position_change ()
848 if ( _length != 0 ) {
849 error << string_compose(_("Filesource: start time is already set for existing file (%1): Cannot change start time."), _path ) << endmsg;
850 //in the future, pop up a dialog here that allows user to regenerate file with new start offset
851 } else if (writable()) {
852 timeline_position = header_position_offset;
853 set_header_timeline_position (); //this will get flushed if/when the file is recorded to
859 SndFileSource::setup_standard_crossfades (nframes_t rate)
861 /* This static method is assumed to have been called by the Session
862 before any DFS's are created.
865 xfade_frames = (nframes_t) floor ((Config->get_destructive_xfade_msecs () / 1000.0) * rate);
867 if (out_coefficient) {
868 delete [] out_coefficient;
871 if (in_coefficient) {
872 delete [] in_coefficient;
875 out_coefficient = new gain_t[xfade_frames];
876 in_coefficient = new gain_t[xfade_frames];
878 compute_equal_power_fades (xfade_frames, in_coefficient, out_coefficient);
882 SndFileSource::set_timeline_position (int64_t pos)
884 // destructive track timeline postion does not change
885 // except at instantion or when header_position_offset
886 // (session start) changes
888 if (!destructive()) {
889 AudioFileSource::set_timeline_position (pos);
894 SndFileSource::get_soundfile_info (string path, SoundFileInfo& info, string& error_msg)
898 SF_BROADCAST_INFO binfo;
899 bool timecode_exists;
901 sf_info.format = 0; // libsndfile says to clear this before sf_open().
903 if ((sf = sf_open ((char*) path.c_str(), SFM_READ, &sf_info)) == 0) {
905 error_msg = sf_error_str (0, errbuf, sizeof (errbuf) - 1);
909 info.samplerate = sf_info.samplerate;
910 info.channels = sf_info.channels;
911 info.length = sf_info.frames;
912 info.format_name = string_compose("Format: %1, %2",
913 sndfile_major_format(sf_info.format),
914 sndfile_minor_format(sf_info.format));
916 memset (&binfo, 0, sizeof (binfo));
917 info.timecode = get_timecode_info (sf, &binfo, timecode_exists);
919 if (!timecode_exists) {
929 SndFileSource::get_timecode_info (SNDFILE* sf, SF_BROADCAST_INFO* binfo, bool& exists)
931 if (sf_command (sf, SFC_GET_BROADCAST_INFO, binfo, sizeof (*binfo)) != SF_TRUE) {
933 return (header_position_offset);
936 /* XXX 64 bit alert: when JACK switches to a 64 bit frame count, this needs to use the high bits
937 of the time reference.
941 int64_t ret = (uint32_t) binfo->time_reference_high;
943 ret |= (uint32_t) binfo->time_reference_low;