use a note tracker to resolve notes cut off during render by the end of the region
[ardour.git] / libs / ardour / export_formats.cc
1 /*
2  * Copyright (C) 2008-2010 Sakari Bergen <sakari.bergen@beatwaves.net>
3  * Copyright (C) 2008-2016 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2009 David Robillard <d@drobilla.net>
5  * Copyright (C) 2017-2019 Robin Gareus <robin@gareus.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "ardour/export_formats.h"
23
24 #include "pbd/i18n.h"
25
26 using namespace std;
27
28 namespace ARDOUR
29 {
30
31 bool
32 ExportFormat::has_sample_format ()
33 {
34         return dynamic_cast<HasSampleFormat *> (this);
35 }
36
37 bool
38 ExportFormat::has_codec_quality ()
39 {
40         return dynamic_cast<HasCodecQuality *> (this);
41 }
42
43
44 bool
45 ExportFormat::sample_format_is_compatible (SampleFormat format) const
46 {
47         return (sample_formats.find (format) != sample_formats.end());
48 }
49
50 /*** HasSampleFormat ***/
51
52 HasSampleFormat::HasSampleFormat (ExportFormatBase::SampleFormatSet & sample_formats) :
53   _sample_formats (sample_formats)
54 {
55         /* Dither Types */
56
57         add_dither_type (ExportFormatBase::D_Shaped, _("Shaped Noise"));
58         add_dither_type (ExportFormatBase::D_Tri, _("Triangular"));
59         add_dither_type (ExportFormatBase::D_Rect, _("Rectangular"));
60         add_dither_type (ExportFormatBase::D_None,  _("None"));
61 }
62
63 void
64 HasSampleFormat::add_sample_format (ExportFormatBase::SampleFormat format)
65 {
66         _sample_formats.insert (format);
67
68         SampleFormatPtr ptr (new SampleFormatState (format, get_sample_format_name (format)));
69         sample_format_states.push_back (ptr);
70         ptr->SelectChanged.connect_same_thread (*this, boost::bind (&HasSampleFormat::update_sample_format_selection, this, _1));
71         // BOOST SIGNALS Could this be made any uglier?
72         ptr->SelectChanged.connect_same_thread (*this,
73                 boost::bind (boost::type<void> (), boost::ref (SampleFormatSelectChanged), _1, WeakSampleFormatPtr (ptr)));
74         ptr->CompatibleChanged.connect_same_thread (*this,
75                 boost::bind (boost::type<void> (), boost::ref (SampleFormatCompatibleChanged), _1, WeakSampleFormatPtr (ptr)));
76 }
77
78 void
79 HasSampleFormat::add_dither_type (ExportFormatBase::DitherType type, string name)
80 {
81         DitherTypePtr ptr (new DitherTypeState (type, name));
82         dither_type_states.push_back (ptr);
83         ptr->SelectChanged.connect_same_thread (*this, boost::bind (&HasSampleFormat::update_dither_type_selection, this, _1));
84         // BOOST SIGNALS Could this be made any uglier?
85         ptr->SelectChanged.connect_same_thread (*this,
86                 boost::bind (boost::type<void> (), boost::ref (DitherTypeSelectChanged), _1, WeakDitherTypePtr (ptr)));
87         ptr->CompatibleChanged.connect_same_thread (*this,
88                 boost::bind (boost::type<void> (),boost::ref ( DitherTypeCompatibleChanged), _1, WeakDitherTypePtr (ptr)));
89 }
90
91 HasSampleFormat::SampleFormatPtr
92 HasSampleFormat::get_selected_sample_format ()
93 {
94         for (SampleFormatList::iterator it = sample_format_states.begin(); it != sample_format_states.end(); ++it) {
95                 if ((*it)->selected()) {
96                         return *it;
97                 }
98         }
99
100         return SampleFormatPtr();
101 }
102
103 HasSampleFormat::DitherTypePtr
104 HasSampleFormat::get_selected_dither_type ()
105 {
106         for (DitherTypeList::iterator it = dither_type_states.begin(); it != dither_type_states.end(); ++it) {
107                 if ((*it)->selected()) {
108                         return *it;
109                 }
110         }
111
112         return DitherTypePtr();
113 }
114
115 void
116 HasSampleFormat::update_sample_format_selection (bool)
117 {
118         SampleFormatPtr format = get_selected_sample_format();
119         if (!format) {
120                 return;
121         }
122
123         if (format->format == ExportFormatBase::SF_24 ||
124             format->format == ExportFormatBase::SF_32 ||
125             format->format == ExportFormatBase::SF_Float ||
126             format->format == ExportFormatBase::SF_Double) {
127                 for (DitherTypeList::iterator it = dither_type_states.begin(); it != dither_type_states.end(); ++it) {
128                         if ((*it)->type == ExportFormatBase::D_None) {
129                                 (*it)->set_selected (true);
130                         } else {
131                                 (*it)->set_compatible (false);
132                         }
133                 }
134
135         } else {
136                 for (DitherTypeList::iterator it = dither_type_states.begin(); it != dither_type_states.end(); ++it) {
137                         (*it)->set_compatible (true);
138                 }
139         }
140 }
141
142 void
143 HasSampleFormat::update_dither_type_selection (bool)
144 {
145         DitherTypePtr type = get_selected_dither_type();
146         if (!type) {
147                 return;
148         }
149
150         if (!type->compatible()) {
151                 SampleFormatPtr format = get_selected_sample_format();
152                 if (format) {
153                         format->set_selected (false);
154                 }
155
156                 for (DitherTypeList::iterator it = dither_type_states.begin(); it != dither_type_states.end(); ++it) {
157                         (*it)->set_compatible (true);
158                 }
159         }
160 }
161
162 string
163 HasSampleFormat::get_sample_format_name (ExportFormatBase::SampleFormat format)
164 {
165         switch (format) {
166           case ExportFormatBase::SF_8:
167                 return _("8-bit");
168           case ExportFormatBase::SF_16:
169                 return _("16-bit");
170           case ExportFormatBase::SF_24:
171                 return _("24-bit");
172           case ExportFormatBase::SF_32:
173                 return _("32-bit");
174           case ExportFormatBase::SF_Float:
175                 return _("float");
176           case ExportFormatBase::SF_Double:
177                 return _("double");
178           case ExportFormatBase::SF_U8:
179                 return _("8-bit unsigned");
180           case ExportFormatBase::SF_Vorbis:
181                 return _("Vorbis sample format");
182           case ExportFormatBase::SF_None:
183                 return _("No sample format");
184         }
185         return "";
186 }
187
188 /*** Linear ***/
189
190 ExportFormatLinear::ExportFormatLinear (string name, FormatId format_id) :
191   HasSampleFormat (sample_formats),
192   _default_sample_format (SF_None)
193 {
194         set_name (name);
195         set_format_id (format_id);
196
197         add_sample_rate (SR_8);
198         add_sample_rate (SR_22_05);
199         add_sample_rate (SR_44_1);
200         add_sample_rate (SR_48);
201         add_sample_rate (SR_88_2);
202         add_sample_rate (SR_96);
203         add_sample_rate (SR_176_4);
204         add_sample_rate (SR_192);
205         add_sample_rate (SR_Session);
206
207         add_endianness (E_FileDefault);
208
209         set_quality (Q_LosslessLinear);
210 }
211
212 bool
213 ExportFormatLinear::set_compatibility_state (ExportFormatCompatibility const & compatibility)
214 {
215         /* Global state */
216
217         bool compatible = true;
218
219         if (!compatibility.has_quality (Q_LosslessLinear)) {
220                 compatible = false;
221         }
222
223         if (!compatibility.has_format (get_format_id())) {
224                 compatible = false;
225         }
226
227         boost::shared_ptr<ExportFormatBase> intersection = get_intersection (compatibility);
228
229         if (intersection->endiannesses_empty()) {
230                 compatible = false;
231         }
232
233         if (intersection->sample_rates_empty()) {
234                 compatible = false;
235         }
236
237         if (intersection->sample_formats_empty()) {
238                 compatible = false;
239         }
240
241         set_compatible (compatible);
242
243         /* Sample Formats */
244
245         for (SampleFormatList::iterator it = sample_format_states.begin(); it != sample_format_states.end(); ++it) {
246                 (*it)->set_compatible (compatibility.has_sample_format ((*it)->format));
247         }
248
249         return compatible;
250 }
251
252 /*** Ogg Vorbis ***/
253
254 ExportFormatOggVorbis::ExportFormatOggVorbis ()
255 {
256         /* Check system compatibility */
257
258         SF_INFO sf_info;
259         sf_info.channels = 2;
260         sf_info.samplerate = SR_44_1;
261         sf_info.format = F_Ogg | SF_Vorbis;
262         if (sf_format_check (&sf_info) != SF_TRUE) {
263                 throw ExportFormatIncompatible();
264         }
265
266         set_name ("Ogg Vorbis");
267         set_format_id (F_Ogg);
268         sample_formats.insert (SF_Vorbis);
269
270         add_sample_rate (SR_22_05);
271         add_sample_rate (SR_44_1);
272         add_sample_rate (SR_48);
273         add_sample_rate (SR_88_2);
274         add_sample_rate (SR_96);
275         add_sample_rate (SR_176_4);
276         add_sample_rate (SR_192);
277         add_sample_rate (SR_Session);
278
279         /* these are 100 vorbis_encode_init_vbr() quality */
280         add_codec_quality ("Low (0)",           0);
281         add_codec_quality ("Default (4)",      40);
282         add_codec_quality ("High (6)",         60);
283         add_codec_quality ("Very High (10)",  100);
284
285         add_endianness (E_FileDefault);
286
287         set_extension ("ogg");
288         set_quality (Q_LossyCompression);
289 }
290
291 bool
292 ExportFormatOggVorbis::set_compatibility_state (ExportFormatCompatibility const & compatibility)
293 {
294         bool compatible = compatibility.has_format (F_Ogg);
295         set_compatible (compatible);
296         return compatible;
297 }
298
299 /*** FLAC ***/
300
301 ExportFormatFLAC::ExportFormatFLAC () :
302   HasSampleFormat (sample_formats)
303 {
304         /* Check system compatibility */
305
306         SF_INFO sf_info;
307         sf_info.channels = 2;
308         sf_info.samplerate = SR_44_1;
309         sf_info.format = F_FLAC | SF_16;
310         if (sf_format_check (&sf_info) != SF_TRUE) {
311                 throw ExportFormatIncompatible();
312         }
313
314         set_name ("FLAC");
315         set_format_id (F_FLAC);
316
317         add_sample_rate (SR_22_05);
318         add_sample_rate (SR_44_1);
319         add_sample_rate (SR_48);
320         add_sample_rate (SR_88_2);
321         add_sample_rate (SR_96);
322         add_sample_rate (SR_176_4);
323         add_sample_rate (SR_192);
324         add_sample_rate (SR_Session);
325
326         add_sample_format (SF_8);
327         add_sample_format (SF_16);
328         add_sample_format (SF_24);
329
330         add_endianness (E_FileDefault);
331
332         set_extension ("flac");
333         set_quality (Q_LosslessCompression);
334 }
335
336 bool
337 ExportFormatFLAC::set_compatibility_state (ExportFormatCompatibility const & compatibility)
338 {
339         bool compatible = compatibility.has_format (F_FLAC);
340         set_compatible (compatible);
341         return compatible;
342 }
343
344 /*** BWF ***/
345
346 ExportFormatBWF::ExportFormatBWF () :
347   HasSampleFormat (sample_formats)
348 {
349         set_name ("BWF");
350         set_format_id (F_WAV);
351
352         add_sample_rate (SR_22_05);
353         add_sample_rate (SR_44_1);
354         add_sample_rate (SR_48);
355         add_sample_rate (SR_88_2);
356         add_sample_rate (SR_96);
357         add_sample_rate (SR_176_4);
358         add_sample_rate (SR_192);
359         add_sample_rate (SR_Session);
360
361         add_sample_format (SF_U8);
362         add_sample_format (SF_16);
363         add_sample_format (SF_24);
364         add_sample_format (SF_32);
365         add_sample_format (SF_Float);
366         add_sample_format (SF_Double);
367
368         add_endianness (E_FileDefault);
369
370         set_extension ("wav");
371         set_quality (Q_LosslessLinear);
372 }
373
374 bool
375 ExportFormatBWF::set_compatibility_state (ExportFormatCompatibility const & compatibility)
376 {
377         bool compatible = compatibility.has_format (F_WAV);
378         set_compatible (compatible);
379         return compatible;
380 }
381
382
383 /*** FFMPEG Pipe ***/
384
385 ExportFormatFFMPEG::ExportFormatFFMPEG (std::string const& name, std::string const& ext)
386 {
387         set_name (name);
388         set_format_id (F_FFMPEG);
389         sample_formats.insert (SF_Float);
390
391         add_sample_rate (SR_8);
392         add_sample_rate (SR_22_05);
393         add_sample_rate (SR_44_1);
394         add_sample_rate (SR_48);
395         add_sample_rate (SR_Session);
396
397         add_endianness (E_Little);
398
399         add_codec_quality ("VBR 220-260 kb/s",  0);
400         add_codec_quality ("VBR 190-250 kb/s", -1);
401         add_codec_quality ("VBR 170-210 kb/s", -2);
402         add_codec_quality ("VBR 150-195 kb/s", -3);
403         add_codec_quality ("VBR 140-185 kb/s", -4);
404         add_codec_quality ("VBR 120-150 kb/s", -5);
405         add_codec_quality ("VBR 100-130 kb/s", -6);
406         add_codec_quality ("VBR 80-120 kb/s",  -7);
407         add_codec_quality ("VBR 70-105 kb/s",  -8);
408         add_codec_quality ("VBR 45-85 kb/s",   -9);
409         /*  Available CBR options are:
410          *  8, 16, 24, 32, 40, 48, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320
411          */
412         add_codec_quality ("CBR  64 kb/s",     64);
413         add_codec_quality ("CBR 128 kb/s",    128);
414         add_codec_quality ("CBR 160 kb/s",    160);
415         add_codec_quality ("CBR 192 kb/s",    192);
416         add_codec_quality ("CBR 256 kb/s",    256);
417         add_codec_quality ("CBR 320 kb/s",    320);
418
419         set_extension (ext);
420         set_quality (Q_LossyCompression);
421 }
422
423 bool
424 ExportFormatFFMPEG::set_compatibility_state (ExportFormatCompatibility const & compatibility)
425 {
426         bool compatible = compatibility.has_format (F_FFMPEG);
427         set_compatible (compatible);
428         return compatible;
429 }
430
431
432 }; // namespace ARDOUR