copy AU parameters with plugin
[ardour.git] / libs / ardour / sndfileimportable.cc
1 /*
2     Copyright (C) 2000,2015 Paul Davis
3
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.
8
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.
13
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17
18 */
19
20 #include <sndfile.h>
21 #include <iostream>
22 #include <cstring>
23
24 #include "pbd/error.h"
25 #include "ardour/sndfileimportable.h"
26
27 #include <glibmm/convert.h>
28
29 using namespace ARDOUR;
30 using namespace std;
31
32 /* FIXME: this was copied from sndfilesource.cc, at some point these should be merged */
33 int64_t
34 SndFileImportableSource::get_timecode_info (SNDFILE* sf, SF_BROADCAST_INFO* binfo, bool& exists)
35 {
36         if (sf_command (sf, SFC_GET_BROADCAST_INFO, binfo, sizeof (*binfo)) != SF_TRUE) {
37                 exists = false;
38                 return 0;
39         }
40
41         /* see http://tracker.ardour.org/view.php?id=6208
42          * 0xffffffff 0xfffc5680
43          * seems to be a bug in Presonus Capture (which generated the file)
44          *
45          * still since framepos_t is a signed int, ignore files that could
46          * lead to negative timestamps for now.
47          */
48
49         if (binfo->time_reference_high & 0x80000000) {
50                 char tmp[64];
51                 snprintf(tmp, sizeof(tmp), "%x%08x", binfo->time_reference_high, binfo->time_reference_low);
52                 PBD::warning << "Invalid Timestamp " << tmp << endmsg;
53                 exists = false;
54                 return 0;
55         }
56
57         exists = true;
58         /* libsndfile reads eactly 4 bytes for high and low, but
59          * uses "unsigned int" which may or may not be 32 bit little
60          * endian.
61          */
62         int64_t ret = (uint32_t) (binfo->time_reference_high & 0x7fffffff);
63         ret <<= 32;
64         ret |= (uint32_t) (binfo->time_reference_low & 0xffffffff);
65
66         assert(ret >= 0);
67         return ret;
68 }
69
70 SndFileImportableSource::SndFileImportableSource (const string& path)
71 {
72         memset(&sf_info, 0 , sizeof(sf_info));
73         in.reset( sf_open(Glib::locale_from_utf8(path).c_str(), SFM_READ, &sf_info), sf_close);
74         if (!in) throw failed_constructor();
75
76         SF_BROADCAST_INFO binfo;
77         bool timecode_exists;
78
79         memset (&binfo, 0, sizeof (binfo));
80         timecode = get_timecode_info (in.get(), &binfo, timecode_exists);
81
82         if (!timecode_exists) {
83                 timecode = 0;
84         }
85 }
86
87 SndFileImportableSource::~SndFileImportableSource ()
88 {
89 }
90
91 framecnt_t
92 SndFileImportableSource::read (Sample* buffer, framecnt_t nframes)
93 {
94         framecnt_t per_channel = nframes / sf_info.channels;
95         per_channel = sf_readf_float (in.get(), buffer, per_channel);
96         return per_channel * sf_info.channels;
97 }
98
99 uint32_t
100 SndFileImportableSource::channels () const
101 {
102         return sf_info.channels;
103 }
104
105 framecnt_t
106 SndFileImportableSource::length () const
107 {
108         return (framecnt_t) sf_info.frames;
109 }
110
111 framecnt_t
112 SndFileImportableSource::samplerate () const
113 {
114         return sf_info.samplerate;
115 }
116
117 void
118 SndFileImportableSource::seek (framepos_t /*pos*/)
119 {
120         sf_seek (in.get(), 0, SEEK_SET);
121 }
122
123 framepos_t
124 SndFileImportableSource::natural_position () const
125 {
126         return (framepos_t) timecode;
127 }
128
129 bool
130 SndFileImportableSource::clamped_at_unity () const
131 {
132         int const type = sf_info.format & SF_FORMAT_TYPEMASK;
133         int const sub = sf_info.format & SF_FORMAT_SUBMASK;
134         /* XXX: this may not be the full list of formats that are unclamped */
135         return (sub != SF_FORMAT_FLOAT && sub != SF_FORMAT_DOUBLE && type != SF_FORMAT_OGG);
136 }