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 <ardour/sndfilesource.h>
25 using namespace ARDOUR;
27 SndFileSource::SndFileSource (const XMLNode& node)
28 : ExternalSource (node)
31 SourceCreated (this); /* EMIT SIGNAL */
34 SndFileSource::SndFileSource (const string& idstr, bool build_peak)
35 : ExternalSource(idstr, build_peak)
37 init (idstr, build_peak);
40 SourceCreated (this); /* EMIT SIGNAL */
45 SndFileSource::init (const string& idstr, bool build_peak)
47 string::size_type pos;
56 if ((pos = idstr.find_last_of (':')) == string::npos) {
60 channel = atoi (idstr.substr (pos+1).c_str());
61 file = idstr.substr (0, pos);
64 /* although libsndfile says we don't need to set this,
65 valgrind and source code shows us that we do.
68 memset (&_info, 0, sizeof(_info));
70 /* note that we temporarily truncated _id at the colon */
72 if ((sf = sf_open (file.c_str(), SFM_READ, &_info)) == 0) {
74 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
75 error << string_compose(_("SndFileSource: cannot open file \"%1\" (%2)"), file, errbuf) << endmsg;
76 throw failed_constructor();
79 if (channel >= _info.channels) {
80 error << string_compose(_("SndFileSource: file only contains %1 channels; %2 is invalid as a channel number"), _info.channels, channel) << endmsg;
83 throw failed_constructor();
86 _length = _info.frames;
90 if (initialize_peakfile (false, _path)) {
93 throw failed_constructor ();
98 SndFileSource::~SndFileSource ()
101 GoingAway (this); /* EMIT SIGNAL */
113 SndFileSource::sample_rate () const
115 return _info.samplerate;
119 SndFileSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const
125 if (sf_seek (sf, (off_t) start, SEEK_SET) < 0) {
127 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
128 error << string_compose(_("SndFileSource: could not seek to frame %1 within %2 (%3)"), start, _name.substr (1), errbuf) << endmsg;
132 if (_info.channels == 1) {
133 jack_nframes_t ret = sf_read_float (sf, dst, cnt);
134 _read_data_count = cnt * sizeof(float);
138 real_cnt = cnt * _info.channels;
141 Glib::Mutex::Lock lm (_tmpbuf_lock);
143 if (tmpbufsize < real_cnt) {
148 tmpbufsize = real_cnt;
149 tmpbuf = new float[tmpbufsize];
152 nread = sf_read_float (sf, tmpbuf, real_cnt);
153 ptr = tmpbuf + channel;
154 nread /= _info.channels;
156 /* stride through the interleaved data */
158 for (int32_t n = 0; n < nread; ++n) {
160 ptr += _info.channels;
164 _read_data_count = cnt * sizeof(float);