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>
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;
183 interleave_bufsize = 0;
189 if ((pos = idstr.find_last_of (':')) == string::npos) {
193 channel = atoi (idstr.substr (pos+1).c_str());
194 tmp_name = idstr.substr (0, pos);
200 _name = Glib::path_get_basename (tmp_name);
203 /* although libsndfile says we don't need to set this,
204 valgrind and source code shows us that we do.
207 memset (&_info, 0, sizeof(_info));
209 _capture_start = false;
210 _capture_end = false;
214 xfade_buf = new Sample[xfade_frames];
215 timeline_position = header_position_offset;
218 AudioFileSource::HeaderPositionOffsetChanged.connect (mem_fun (*this, &SndFileSource::handle_header_position_change));
222 SndFileSource::open ()
224 if ((sf = sf_open (_path.c_str(), (writable() ? SFM_RDWR : SFM_READ), &_info)) == 0) {
226 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
227 error << string_compose(_("SndFileSource: cannot open file \"%1\" for %2 (%3)"),
228 _path, (writable() ? "read+write" : "reading"), errbuf) << endmsg;
232 if (channel >= _info.channels) {
233 error << string_compose(_("SndFileSource: file only contains %1 channels; %2 is invalid as a channel number"), _info.channels, channel) << endmsg;
239 _length = _info.frames;
241 _broadcast_info = new SF_BROADCAST_INFO;
242 memset (_broadcast_info, 0, sizeof (*_broadcast_info));
244 /* lookup broadcast info */
246 if (sf_command (sf, SFC_GET_BROADCAST_INFO, _broadcast_info, sizeof (*_broadcast_info)) != SF_TRUE) {
248 /* if the file has data but no broadcast info, then clearly, there is no broadcast info */
251 delete _broadcast_info;
253 _flags = Flag (_flags & ~Broadcast);
256 set_timeline_position (header_position_offset);
260 /* XXX 64 bit alert: when JACK switches to a 64 bit frame count, this needs to use the high bits
261 of the time reference.
264 set_timeline_position ( _broadcast_info->time_reference_low );
268 sf_command (sf, SFC_SET_UPDATE_HEADER_AUTO, 0, SF_FALSE);
274 SndFileSource::~SndFileSource ()
276 GoingAway (); /* EMIT SIGNAL */
282 /* stupid libsndfile updated the headers on close,
283 so touch the peakfile if it exists and has data
284 to make sure its time is as new as the audio
291 if (interleave_buf) {
292 delete [] interleave_buf;
295 if (_broadcast_info) {
296 delete _broadcast_info;
305 SndFileSource::sample_rate () const
307 return _info.samplerate;
311 SndFileSource::read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const
318 if (start > _length) {
320 /* read starts beyond end of data, just memset to zero */
324 } else if (start + cnt > _length) {
326 /* read ends beyond end of data, read some, memset the rest */
328 file_cnt = _length - start;
332 /* read is entirely within data */
339 if (sf_seek (sf, (sf_count_t) start, SEEK_SET|SFM_READ) != (sf_count_t) start) {
341 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
342 error << string_compose(_("SndFileSource: could not seek to frame %1 within %2 (%3)"), start, _name.substr (1), errbuf) << endmsg;
346 if (_info.channels == 1) {
347 nframes_t ret = sf_read_float (sf, dst, file_cnt);
348 _read_data_count = cnt * sizeof(float);
353 if (file_cnt != cnt) {
354 nframes_t delta = cnt - file_cnt;
355 memset (dst+file_cnt, 0, sizeof (Sample) * delta);
358 real_cnt = cnt * _info.channels;
360 if (interleave_bufsize < real_cnt) {
362 if (interleave_buf) {
363 delete [] interleave_buf;
365 interleave_bufsize = real_cnt;
366 interleave_buf = new float[interleave_bufsize];
369 nread = sf_read_float (sf, interleave_buf, real_cnt);
370 ptr = interleave_buf + channel;
371 nread /= _info.channels;
373 /* stride through the interleaved data */
375 for (int32_t n = 0; n < nread; ++n) {
377 ptr += _info.channels;
380 _read_data_count = cnt * sizeof(float);
386 SndFileSource::write_unlocked (Sample *data, nframes_t cnt)
389 return destructive_write_unlocked (data, cnt);
391 return nondestructive_write_unlocked (data, cnt);
396 SndFileSource::nondestructive_write_unlocked (Sample *data, nframes_t cnt)
402 if (_info.channels != 1) {
403 fatal << string_compose (_("programming error: %1 %2"), X_("SndFileSource::write called on non-mono file"), _path) << endmsg;
409 int32_t frame_pos = _length;
411 if (write_float (data, frame_pos, cnt) != cnt) {
416 update_length (oldlen, cnt);
418 if (_build_peakfiles) {
419 PeakBuildRecord *pbr = 0;
421 if (pending_peak_builds.size()) {
422 pbr = pending_peak_builds.back();
425 if (pbr && pbr->frame + pbr->cnt == oldlen) {
427 /* the last PBR extended to the start of the current write,
428 so just extend it again.
433 pending_peak_builds.push_back (new PeakBuildRecord (oldlen, cnt));
436 _peaks_built = false;
440 if (_build_peakfiles) {
441 queue_for_peaks (shared_from_this ());
444 _write_data_count = cnt;
450 SndFileSource::destructive_write_unlocked (Sample* data, nframes_t cnt)
452 nframes_t old_file_pos;
458 if (_capture_start && _capture_end) {
460 /* start and end of capture both occur within the data we are writing,
461 so do both crossfades.
464 _capture_start = false;
465 _capture_end = false;
467 /* move to the correct location place */
468 file_pos = capture_start_frame - timeline_position;
471 nframes_t subcnt = cnt / 2;
472 nframes_t ofilepos = file_pos;
475 if (crossfade (data, subcnt, 1) != subcnt) {
480 Sample * tmpdata = data + subcnt;
483 subcnt = cnt - subcnt;
484 if (crossfade (tmpdata, subcnt, 0) != subcnt) {
488 file_pos = ofilepos; // adjusted below
490 } else if (_capture_start) {
492 /* start of capture both occur within the data we are writing,
496 _capture_start = false;
497 _capture_end = false;
499 /* move to the correct location place */
500 file_pos = capture_start_frame - timeline_position;
502 if (crossfade (data, cnt, 1) != cnt) {
506 } else if (_capture_end) {
508 /* end of capture both occur within the data we are writing,
512 _capture_start = false;
513 _capture_end = false;
515 if (crossfade (data, cnt, 0) != cnt) {
521 /* in the middle of recording */
523 if (write_float (data, file_pos, cnt) != cnt) {
528 old_file_pos = file_pos;
529 update_length (file_pos, cnt);
532 if (_build_peakfiles) {
533 PeakBuildRecord *pbr = 0;
535 if (pending_peak_builds.size()) {
536 pbr = pending_peak_builds.back();
539 if (pbr && pbr->frame + pbr->cnt == old_file_pos) {
541 /* the last PBR extended to the start of the current write,
542 so just extend it again.
547 pending_peak_builds.push_back (new PeakBuildRecord (old_file_pos, cnt));
550 _peaks_built = false;
553 if (_build_peakfiles) {
554 queue_for_peaks (shared_from_this ());
561 SndFileSource::update_header (nframes_t when, struct tm& now, time_t tnow)
563 set_timeline_position (when);
565 if (_flags & Broadcast) {
566 if (setup_broadcast_info (when, now, tnow)) {
571 return flush_header ();
575 SndFileSource::flush_header ()
577 if (!writable() || (sf == 0)) {
580 return (sf_command (sf, SFC_UPDATE_HEADER_NOW, 0, 0) != SF_TRUE);
584 SndFileSource::setup_broadcast_info (nframes_t when, struct tm& now, time_t tnow)
590 if (!(_flags & Broadcast)) {
594 /* random code is 9 digits */
596 int random_code = random() % 999999999;
598 snprintf (_broadcast_info->originator_reference, sizeof (_broadcast_info->originator_reference), "%2s%3s%12s%02d%02d%02d%9d",
599 Config->get_bwf_country_code().c_str(),
600 Config->get_bwf_organization_code().c_str(),
607 snprintf (_broadcast_info->origination_date, sizeof (_broadcast_info->origination_date), "%4d-%02d-%02d",
612 snprintf (_broadcast_info->origination_time, sizeof (_broadcast_info->origination_time), "%02d:%02d:%02d",
617 /* now update header position taking header offset into account */
619 set_header_timeline_position ();
621 if (sf_command (sf, SFC_SET_BROADCAST_INFO, _broadcast_info, sizeof (*_broadcast_info)) != SF_TRUE) {
622 error << string_compose (_("cannot set broadcast info for audio file %1; Dropping broadcast info for this file"), _path) << endmsg;
623 _flags = Flag (_flags & ~Broadcast);
624 delete _broadcast_info;
633 SndFileSource::set_header_timeline_position ()
635 if (!(_flags & Broadcast)) {
639 _broadcast_info->time_reference_high = (timeline_position >> 32);
640 _broadcast_info->time_reference_low = (timeline_position & 0xffffffff);
642 if (sf_command (sf, SFC_SET_BROADCAST_INFO, _broadcast_info, sizeof (*_broadcast_info)) != SF_TRUE) {
643 error << string_compose (_("cannot set broadcast info for audio file %1; Dropping broadcast info for this file"), _path) << endmsg;
644 _flags = Flag (_flags & ~Broadcast);
645 delete _broadcast_info;
654 SndFileSource::write_float (Sample* data, nframes_t frame_pos, nframes_t cnt)
656 if (sf_seek (sf, frame_pos, SEEK_SET|SFM_WRITE) < 0) {
658 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
659 error << string_compose (_("%1: cannot seek to %2 (libsndfile error: %3"), _path, frame_pos, errbuf) << endmsg;
663 if (sf_writef_float (sf, data, cnt) != (ssize_t) cnt) {
671 SndFileSource::natural_position() const
673 return timeline_position;
677 SndFileSource::set_destructive (bool yn)
680 _flags = Flag (_flags | Destructive);
681 clear_capture_marks ();
682 timeline_position = header_position_offset;
684 _flags = Flag (_flags & ~Destructive);
685 timeline_position = 0;
692 SndFileSource::clear_capture_marks ()
694 _capture_start = false;
695 _capture_end = false;
699 SndFileSource::mark_capture_start (nframes_t pos)
702 if (pos < timeline_position) {
703 _capture_start = false;
705 _capture_start = true;
706 capture_start_frame = pos;
712 SndFileSource::mark_capture_end()
720 SndFileSource::crossfade (Sample* data, nframes_t cnt, int fade_in)
722 nframes_t xfade = min (xfade_frames, cnt);
723 nframes_t nofade = cnt - xfade;
724 Sample* fade_data = 0;
725 nframes_t fade_position = 0; // in frames
730 fade_position = file_pos;
733 fade_position = file_pos + nofade;
734 fade_data = data + nofade;
737 if (fade_position > _length) {
739 /* read starts beyond end of data, just memset to zero */
743 } else if (fade_position + xfade > _length) {
745 /* read ends beyond end of data, read some, memset the rest */
747 file_cnt = _length - fade_position;
751 /* read is entirely within data */
758 if ((retval = read_unlocked (xfade_buf, fade_position, file_cnt)) != (ssize_t) file_cnt) {
759 if (retval >= 0 && errno == EAGAIN) {
760 /* XXX - can we really trust that errno is meaningful here? yes POSIX, i'm talking to you.
761 * short or no data there */
762 memset (xfade_buf, 0, xfade * sizeof(Sample));
764 error << string_compose(_("SndFileSource: \"%1\" bad read retval: %2 of %5 (%3: %4)"), _path, retval, errno, strerror (errno), xfade) << endmsg;
770 if (file_cnt != xfade) {
771 nframes_t delta = xfade - file_cnt;
772 memset (xfade_buf+file_cnt, 0, sizeof (Sample) * delta);
775 if (nofade && !fade_in) {
776 if (write_float (data, file_pos, nofade) != nofade) {
777 error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
782 if (xfade == xfade_frames) {
786 /* use the standard xfade curve */
790 /* fade new material in */
792 for (n = 0; n < xfade; ++n) {
793 xfade_buf[n] = (xfade_buf[n] * out_coefficient[n]) + (fade_data[n] * in_coefficient[n]);
799 /* fade new material out */
801 for (n = 0; n < xfade; ++n) {
802 xfade_buf[n] = (xfade_buf[n] * in_coefficient[n]) + (fade_data[n] * out_coefficient[n]);
811 /* short xfade, compute custom curve */
813 compute_equal_power_fades (xfade, in, out);
815 for (nframes_t n = 0; n < xfade; ++n) {
816 xfade_buf[n] = (xfade_buf[n] * out[n]) + (fade_data[n] * in[n]);
821 if (write_float (xfade_buf, fade_position, xfade) != xfade) {
822 error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
827 if (fade_in && nofade) {
828 if (write_float (data + xfade, file_pos + xfade, nofade) != nofade) {
829 error << string_compose(_("SndFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
838 SndFileSource::last_capture_start_frame () const
840 return capture_start_frame;
844 SndFileSource::handle_header_position_change ()
847 if ( _length != 0 ) {
848 error << string_compose(_("Filesource: start time is already set for existing file (%1): Cannot change start time."), _path ) << endmsg;
849 //in the future, pop up a dialog here that allows user to regenerate file with new start offset
850 } else if (writable()) {
851 timeline_position = header_position_offset;
852 set_header_timeline_position (); //this will get flushed if/when the file is recorded to
858 SndFileSource::setup_standard_crossfades (nframes_t rate)
860 /* This static method is assumed to have been called by the Session
861 before any DFS's are created.
864 xfade_frames = (nframes_t) floor ((Config->get_destructive_xfade_msecs () / 1000.0) * rate);
866 cerr << "based on " << Config->get_destructive_xfade_msecs() << " msecs, xfade_frames = " << xfade_frames << endl;
868 if (out_coefficient) {
869 delete [] out_coefficient;
872 if (in_coefficient) {
873 delete [] in_coefficient;
876 out_coefficient = new gain_t[xfade_frames];
877 in_coefficient = new gain_t[xfade_frames];
879 compute_equal_power_fades (xfade_frames, in_coefficient, out_coefficient);
883 SndFileSource::set_timeline_position (nframes_t pos)
885 // destructive track timeline postion does not change
886 // except at instantion or when header_position_offset
887 // (session start) changes
889 if (!destructive()) {
890 AudioFileSource::set_timeline_position (pos);