2 Copyright (C) 2000 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 "libardour-config.h"
35 #include <samplerate.h>
37 #include <glib/gstdio.h>
40 #include <boost/scoped_array.hpp>
41 #include <boost/shared_array.hpp>
43 #include "pbd/basename.h"
44 #include "pbd/convert.h"
46 #include "evoral/SMF.hpp"
48 #include "ardour/analyser.h"
49 #include "ardour/ardour.h"
50 #include "ardour/audio_diskstream.h"
51 #include "ardour/audioengine.h"
52 #include "ardour/audioregion.h"
53 #include "ardour/import_status.h"
54 #include "ardour/region_factory.h"
55 #include "ardour/resampled_source.h"
56 #include "ardour/runtime_functions.h"
57 #include "ardour/session.h"
58 #include "ardour/session_directory.h"
59 #include "ardour/smf_source.h"
60 #include "ardour/sndfile_helpers.h"
61 #include "ardour/sndfileimportable.h"
62 #include "ardour/sndfilesource.h"
63 #include "ardour/source_factory.h"
64 #include "ardour/tempo.h"
67 #include "ardour/caimportable.h"
73 using namespace ARDOUR;
76 static boost::shared_ptr<ImportableSource>
77 open_importable_source (const string& path, framecnt_t samplerate, ARDOUR::SrcQuality quality)
79 /* try libsndfile first, because it can get BWF info from .wav, which ExtAudioFile cannot.
80 We don't necessarily need that information in an ImportableSource, but it keeps the
81 logic the same as in SourceFactory::create()
85 boost::shared_ptr<SndFileImportableSource> source(new SndFileImportableSource(path));
87 if (source->samplerate() == samplerate) {
91 /* rewrap as a resampled source */
93 return boost::shared_ptr<ImportableSource>(new ResampledImportableSource(source, samplerate, quality));
100 /* libsndfile failed, see if we can use CoreAudio to handle the IO */
102 CAImportableSource* src = new CAImportableSource(path);
103 boost::shared_ptr<CAImportableSource> source (src);
105 if (source->samplerate() == samplerate) {
109 /* rewrap as a resampled source */
111 return boost::shared_ptr<ImportableSource>(new ResampledImportableSource(source, samplerate, quality));
121 Session::get_paths_for_new_sources (bool /*allow_replacing*/, const string& import_file_path, uint32_t channels)
123 vector<string> new_paths;
124 const string basename = basename_nosuffix (import_file_path);
126 for (uint32_t n = 0; n < channels; ++n) {
128 const DataType type = SMFSource::safe_midi_file_extension (import_file_path) ? DataType::MIDI : DataType::AUDIO;
133 filepath = new_midi_source_path (basename);
135 case DataType::AUDIO:
136 filepath = new_audio_source_path (basename, channels, n, false, false);
140 if (filepath.empty()) {
141 error << string_compose (_("Cannot find new filename for imported file %1"), import_file_path) << endmsg;
142 return vector<string>();
145 new_paths.push_back (filepath);
152 map_existing_mono_sources (const vector<string>& new_paths, Session& /*sess*/,
153 uint32_t /*samplerate*/, vector<boost::shared_ptr<Source> >& newfiles, Session *session)
155 for (vector<string>::const_iterator i = new_paths.begin();
156 i != new_paths.end(); ++i)
158 boost::shared_ptr<Source> source = session->audio_source_by_path_and_channel(*i, 0);
161 error << string_compose(_("Could not find a source for %1 even though we are updating this file!"), (*i)) << endl;
165 newfiles.push_back(boost::dynamic_pointer_cast<Source>(source));
171 create_mono_sources_for_writing (const vector<string>& new_paths,
172 Session& sess, uint32_t samplerate,
173 vector<boost::shared_ptr<Source> >& newfiles,
174 framepos_t timeline_position)
176 for (vector<string>::const_iterator i = new_paths.begin(); i != new_paths.end(); ++i) {
178 boost::shared_ptr<Source> source;
181 const DataType type = SMFSource::safe_midi_file_extension (*i) ? DataType::MIDI : DataType::AUDIO;
183 source = SourceFactory::createWritable (type, sess,
185 false, // destructive
189 catch (const failed_constructor& err) {
190 error << string_compose (_("Unable to create file %1 during import"), *i) << endmsg;
194 newfiles.push_back(boost::dynamic_pointer_cast<Source>(source));
196 /* for audio files, reset the timeline position so that any BWF-ish
197 information in the original files we are importing from is maintained.
200 boost::shared_ptr<AudioFileSource> afs;
201 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
202 afs->set_timeline_position(timeline_position);
209 compose_status_message (const string& path,
210 uint32_t file_samplerate,
211 uint32_t session_samplerate,
212 uint32_t /* current_file */,
213 uint32_t /* total_files */)
215 if (file_samplerate != session_samplerate) {
216 return string_compose (_("Resampling %1 from %2kHz to %3kHz"),
217 Glib::path_get_basename (path),
218 file_samplerate/1000.0f,
219 session_samplerate/1000.0f);
222 return string_compose (_("Copying %1"), Glib::path_get_basename (path));
226 write_audio_data_to_new_files (ImportableSource* source, ImportStatus& status,
227 vector<boost::shared_ptr<Source> >& newfiles)
229 const framecnt_t nframes = ResampledImportableSource::blocksize;
230 boost::shared_ptr<AudioFileSource> afs;
231 uint32_t channels = source->channels();
233 boost::scoped_array<float> data(new float[nframes * channels]);
234 vector<boost::shared_array<Sample> > channel_data;
236 for (uint32_t n = 0; n < channels; ++n) {
237 channel_data.push_back(boost::shared_array<Sample>(new Sample[nframes]));
242 boost::shared_ptr<AudioSource> s = boost::dynamic_pointer_cast<AudioSource> (newfiles[0]);
245 status.progress = 0.0f;
246 float progress_multiplier = 1;
247 float progress_base = 0;
249 if (!source->clamped_at_unity() && s->clamped_at_unity()) {
251 /* The source we are importing from can return sample values with a magnitude greater than 1,
252 and the file we are writing the imported data to cannot handle such values. Compute the gain
253 factor required to normalize the input sources to have a magnitude of less than 1.
257 uint32_t read_count = 0;
259 while (!status.cancel) {
260 framecnt_t const nread = source->read (data.get(), nframes);
265 peak = compute_peak (data.get(), nread, peak);
268 status.progress = 0.5 * read_count / (source->ratio() * source->length() * channels);
272 /* we are out of range: compute a gain to fix it */
273 gain = (1 - FLT_EPSILON) / peak;
277 progress_multiplier = 0.5;
281 framecnt_t read_count = 0;
283 while (!status.cancel) {
285 framecnt_t nread, nfread;
289 if ((nread = source->read (data.get(), nframes)) == 0) {
290 #ifdef PLATFORM_WINDOWS
291 /* Flush the data once we've finished importing the file. Windows can */
292 /* cache the data for very long periods of time (perhaps not writing */
293 /* it to disk until Ardour closes). So let's force it to flush now. */
294 for (chn = 0; chn < channels; ++chn)
295 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(newfiles[chn])) != 0)
302 /* here is the gain fix for out-of-range sample values that we computed earlier */
303 apply_gain_to_buffer (data.get(), nread, gain);
306 nfread = nread / channels;
310 for (chn = 0; chn < channels; ++chn) {
313 for (x = chn, n = 0; n < nfread; x += channels, ++n) {
314 channel_data[chn][n] = (Sample) data[x];
320 for (chn = 0; chn < channels; ++chn) {
321 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(newfiles[chn])) != 0) {
322 afs->write (channel_data[chn].get(), nfread);
327 status.progress = progress_base + progress_multiplier * read_count / (source->ratio () * source->length() * channels);
332 write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
333 vector<boost::shared_ptr<Source> >& newfiles)
335 uint32_t buf_size = 4;
336 uint8_t* buf = (uint8_t*) malloc (buf_size);
338 status.progress = 0.0f;
340 assert (newfiles.size() == source->num_tracks());
343 vector<boost::shared_ptr<Source> >::iterator s = newfiles.begin();
345 for (unsigned i = 1; i <= source->num_tracks(); ++i) {
347 boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource> (*s);
350 source->seek_to_track (i);
353 uint32_t delta_t = 0;
357 while (!status.cancel) {
358 gint note_id_ignored; // imported files either don't have NoteID's or we ignore them.
362 int ret = source->read_event (&delta_t, &size, &buf, ¬e_id_ignored);
364 if (size > buf_size) {
368 if (ret < 0) { // EOT
374 if (ret == 0) { // Meta
379 smfs->mark_streaming_write_started ();
383 smfs->append_event_unlocked_beats(
384 Evoral::Event<double>(0,
385 (double)t / (double)source->ppqn(),
389 if (status.progress < 0.99) {
390 status.progress += 0.01;
396 /* we wrote something */
398 const framepos_t pos = 0;
399 const double length_beats = ceil(t / (double)source->ppqn());
400 BeatsFramesConverter converter(smfs->session().tempo_map(), pos);
401 smfs->update_length(pos + converter.to(length_beats));
402 smfs->mark_streaming_write_completed ();
408 warning << string_compose (_("Track %1 of %2 contained no usable MIDI data"), i, source->file_path()) << endmsg;
415 error << string_compose (_("MIDI file %1 was not readable (no reason available)"), source->file_path()) << endmsg;
424 remove_file_source (boost::shared_ptr<Source> source)
426 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (source);
429 ::g_unlink (fs->path().c_str());
433 // This function is still unable to cleanly update an existing source, even though
434 // it is possible to set the ImportStatus flag accordingly. The functinality
435 // is disabled at the GUI until the Source implementations are able to provide
436 // the necessary API.
438 Session::import_files (ImportStatus& status)
440 typedef vector<boost::shared_ptr<Source> > Sources;
441 Sources all_new_sources;
442 boost::shared_ptr<AudioFileSource> afs;
443 boost::shared_ptr<SMFSource> smfs;
444 uint32_t channels = 0;
446 status.sources.clear ();
448 for (vector<string>::iterator p = status.paths.begin();
449 p != status.paths.end() && !status.cancel;
452 boost::shared_ptr<ImportableSource> source;
453 std::auto_ptr<Evoral::SMF> smf_reader;
454 const DataType type = SMFSource::safe_midi_file_extension (*p) ? DataType::MIDI : DataType::AUDIO;
456 if (type == DataType::AUDIO) {
458 source = open_importable_source (*p, frame_rate(), status.quality);
459 channels = source->channels();
460 } catch (const failed_constructor& err) {
461 error << string_compose(_("Import: cannot open input sound file \"%1\""), (*p)) << endmsg;
462 status.done = status.cancel = true;
468 smf_reader = std::auto_ptr<Evoral::SMF>(new Evoral::SMF());
469 smf_reader->open(*p);
470 channels = smf_reader->num_tracks();
472 error << _("Import: error opening MIDI file") << endmsg;
473 status.done = status.cancel = true;
479 error << _("Import: file contains no channels.") << endmsg;
483 vector<string> new_paths = get_paths_for_new_sources (status.replace_existing_source, *p, channels);
485 framepos_t natural_position = source ? source->natural_position() : 0;
488 if (status.replace_existing_source) {
489 fatal << "THIS IS NOT IMPLEMENTED YET, IT SHOULD NEVER GET CALLED!!! DYING!" << endmsg;
490 status.cancel = !map_existing_mono_sources (new_paths, *this, frame_rate(), newfiles, this);
492 status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles, natural_position);
495 // copy on cancel/failure so that any files that were created will be removed below
496 std::copy (newfiles.begin(), newfiles.end(), std::back_inserter(all_new_sources));
502 for (Sources::iterator i = newfiles.begin(); i != newfiles.end(); ++i) {
503 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*i)) != 0) {
504 afs->prepare_for_peakfile_writes ();
508 if (source) { // audio
509 status.doing_what = compose_status_message (*p, source->samplerate(),
510 frame_rate(), status.current, status.total);
511 write_audio_data_to_new_files (source.get(), status, newfiles);
512 } else if (smf_reader.get()) { // midi
513 status.doing_what = string_compose(_("Loading MIDI file %1"), *p);
514 write_midi_data_to_new_files (smf_reader.get(), status, newfiles);
521 if (!status.cancel) {
525 now = localtime (&xnow);
526 status.freeze = true;
528 /* flush the final length(s) to the header(s) */
530 for (Sources::iterator x = all_new_sources.begin(); x != all_new_sources.end(); ) {
532 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*x)) != 0) {
533 afs->update_header((*x)->natural_position(), *now, xnow);
534 afs->done_with_peakfile_writes ();
536 /* now that there is data there, requeue the file for analysis */
538 if (Config->get_auto_analyse_audio()) {
539 Analyser::queue_source_for_analysis (boost::static_pointer_cast<Source>(*x), false);
543 /* imported, copied files cannot be written or removed
546 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource>(*x);
548 /* Only audio files should be marked as
549 immutable - we may need to rewrite MIDI
552 if (boost::dynamic_pointer_cast<AudioFileSource> (fs)) {
553 fs->mark_immutable ();
555 fs->mark_immutable_except_write ();
557 fs->mark_nonremovable ();
560 /* don't create tracks for empty MIDI sources (channels) */
562 if ((smfs = boost::dynamic_pointer_cast<SMFSource>(*x)) != 0 && smfs->is_empty()) {
563 x = all_new_sources.erase(x);
569 /* save state so that we don't lose these new Sources */
573 std::copy (all_new_sources.begin(), all_new_sources.end(), std::back_inserter(status.sources));
576 std::for_each (all_new_sources.begin(), all_new_sources.end(), remove_file_source);
578 error << _("Failed to remove some files after failed/cancelled import operation") << endmsg;