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.
22 #include "libardour-config.h"
36 #include <samplerate.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/session.h"
57 #include "ardour/session_directory.h"
58 #include "ardour/smf_source.h"
59 #include "ardour/sndfile_helpers.h"
60 #include "ardour/sndfileimportable.h"
61 #include "ardour/sndfilesource.h"
62 #include "ardour/source_factory.h"
63 #include "ardour/tempo.h"
66 #include "ardour/caimportable.h"
72 using namespace ARDOUR;
75 static boost::shared_ptr<ImportableSource>
76 open_importable_source (const string& path, nframes_t samplerate, ARDOUR::SrcQuality quality)
78 /* try libsndfile first, because it can get BWF info from .wav, which ExtAudioFile cannot.
79 We don't necessarily need that information in an ImportableSource, but it keeps the
80 logic the same as in SourceFactory::create()
84 boost::shared_ptr<SndFileImportableSource> source(new SndFileImportableSource(path));
86 if (source->samplerate() == samplerate) {
90 /* rewrap as a resampled source */
92 return boost::shared_ptr<ImportableSource>(new ResampledImportableSource(source, samplerate, quality));
99 /* libsndfile failed, see if we can use CoreAudio to handle the IO */
101 CAImportableSource* src = new CAImportableSource(path);
102 boost::shared_ptr<CAImportableSource> source (src);
104 if (source->samplerate() == samplerate) {
108 /* rewrap as a resampled source */
110 return boost::shared_ptr<ImportableSource>(new ResampledImportableSource(source, samplerate, quality));
120 get_non_existent_filename (DataType type, const bool allow_replacing, const std::string& destdir, const std::string& basename, uint channel, uint channels)
122 char buf[PATH_MAX+1];
123 bool goodfile = false;
124 string base(basename);
125 const char* ext = (type == DataType::AUDIO) ? "wav" : "mid";
129 if (type == DataType::AUDIO && channels == 2) {
131 snprintf (buf, sizeof(buf), "%s-L.wav", base.c_str());
133 snprintf (buf, sizeof(buf), "%s-R.wav", base.c_str());
135 } else if (channels > 1) {
136 snprintf (buf, sizeof(buf), "%s-c%d.%s", base.c_str(), channel, ext);
138 snprintf (buf, sizeof(buf), "%s.%s", base.c_str(), ext);
142 string tempname = destdir + "/" + buf;
143 if (!allow_replacing && Glib::file_test (tempname, Glib::FILE_TEST_EXISTS)) {
145 /* if the file already exists, we must come up with
146 * a new name for it. for now we just keep appending
157 } while ( !goodfile);
162 static vector<string>
163 get_paths_for_new_sources (const bool allow_replacing, const string& import_file_path, const string& session_dir, uint channels)
165 vector<string> new_paths;
166 const string basename = basename_nosuffix (import_file_path);
168 SessionDirectory sdir(session_dir);
170 for (uint n = 0; n < channels; ++n) {
172 const DataType type = SMFSource::safe_midi_file_extension (import_file_path) ? DataType::MIDI : DataType::AUDIO;
174 std::string filepath = (type == DataType::MIDI)
175 ? sdir.midi_path().to_string() : sdir.sound_path().to_string();
178 filepath += get_non_existent_filename (type, allow_replacing, filepath, basename, n, channels);
179 new_paths.push_back (filepath);
186 map_existing_mono_sources (const vector<string>& new_paths, Session& /*sess*/,
187 uint /*samplerate*/, vector<boost::shared_ptr<Source> >& newfiles, Session *session)
189 for (vector<string>::const_iterator i = new_paths.begin();
190 i != new_paths.end(); ++i)
192 boost::shared_ptr<Source> source = session->source_by_path_and_channel(*i, 0);
195 error << string_compose(_("Could not find a source for %1 even though we are updating this file!"), (*i)) << endl;
199 newfiles.push_back(boost::dynamic_pointer_cast<Source>(source));
205 create_mono_sources_for_writing (const vector<string>& new_paths, Session& sess,
206 uint samplerate, vector<boost::shared_ptr<Source> >& newfiles,
207 framepos_t timeline_position)
209 for (vector<string>::const_iterator i = new_paths.begin(); i != new_paths.end(); ++i)
211 boost::shared_ptr<Source> source;
215 const DataType type = SMFSource::safe_midi_file_extension (*i) ? DataType::MIDI : DataType::AUDIO;
218 source = SourceFactory::createWritable (type, sess,
220 false, // destructive
223 catch (const failed_constructor& err)
225 error << string_compose (_("Unable to create file %1 during import"), *i) << endmsg;
229 newfiles.push_back(boost::dynamic_pointer_cast<Source>(source));
231 /* for audio files, reset the timeline position so that any BWF-ish
232 information in the original files we are importing from is maintained.
235 boost::shared_ptr<AudioFileSource> afs;
236 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
237 afs->set_timeline_position(timeline_position);
244 compose_status_message (const string& path,
245 uint file_samplerate,
246 uint session_samplerate,
250 if (file_samplerate != session_samplerate) {
251 return string_compose (_("Resampling %1 from %2kHz to %3kHz"),
252 Glib::path_get_basename (path),
253 file_samplerate/1000.0f,
254 session_samplerate/1000.0f);
257 return string_compose (_("Copying %1"), Glib::path_get_basename (path));
261 write_audio_data_to_new_files (ImportableSource* source, ImportStatus& status,
262 vector<boost::shared_ptr<Source> >& newfiles)
264 const nframes_t nframes = ResampledImportableSource::blocksize;
265 boost::shared_ptr<AudioFileSource> afs;
266 uint channels = source->channels();
268 boost::scoped_array<float> data(new float[nframes * channels]);
269 vector<boost::shared_array<Sample> > channel_data;
271 for (uint n = 0; n < channels; ++n) {
272 channel_data.push_back(boost::shared_array<Sample>(new Sample[nframes]));
277 boost::shared_ptr<AudioSource> s = boost::dynamic_pointer_cast<AudioSource> (newfiles[0]);
280 status.progress = 0.0f;
281 float progress_multiplier = 1;
282 float progress_base = 0;
284 if (!source->clamped_at_unity() && s->clamped_at_unity()) {
286 /* The source we are importing from can return sample values with a magnitude greater than 1,
287 and the file we are writing the imported data to cannot handle such values. Compute the gain
288 factor required to normalize the input sources to have a magnitude of less than 1.
294 while (!status.cancel) {
295 nframes_t const nread = source->read (data.get(), nframes);
300 peak = compute_peak (data.get(), nread, peak);
303 status.progress = 0.5 * read_count / (source->ratio() * source->length() * channels);
307 /* we are out of range: compute a gain to fix it */
308 gain = (1 - FLT_EPSILON) / peak;
312 progress_multiplier = 0.5;
318 while (!status.cancel) {
320 nframes_t nread, nfread;
324 if ((nread = source->read (data.get(), nframes)) == 0) {
329 /* here is the gain fix for out-of-range sample values that we computed earlier */
330 apply_gain_to_buffer (data.get(), nread, gain);
333 nfread = nread / channels;
337 for (chn = 0; chn < channels; ++chn) {
340 for (x = chn, n = 0; n < nfread; x += channels, ++n) {
341 channel_data[chn][n] = (Sample) data[x];
347 for (chn = 0; chn < channels; ++chn) {
348 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(newfiles[chn])) != 0) {
349 afs->write (channel_data[chn].get(), nfread);
354 status.progress = progress_base + progress_multiplier * read_count / (source->ratio () * source->length() * channels);
359 write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
360 vector<boost::shared_ptr<Source> >& newfiles)
362 uint32_t buf_size = 4;
363 uint8_t* buf = (uint8_t*)malloc(buf_size);
365 status.progress = 0.0f;
369 for (unsigned i = 1; i <= source->num_tracks(); ++i) {
370 boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource>(newfiles[i-1]);
373 source->seek_to_track(i);
376 uint32_t delta_t = 0;
380 while (!status.cancel) {
383 int ret = source->read_event(&delta_t, &size, &buf);
387 if (ret < 0) { // EOT
393 if (ret == 0) { // Meta
398 smfs->mark_streaming_write_started ();
402 smfs->append_event_unlocked_beats(Evoral::Event<double>(0,
403 (double)t / (double)source->ppqn(),
407 if (status.progress < 0.99)
408 status.progress += 0.01;
411 const nframes64_t pos = 0;
412 const double length_beats = ceil(t / (double)source->ppqn());
413 BeatsFramesConverter converter(smfs->session().tempo_map(), pos);
414 smfs->update_length(pos, converter.to(length_beats));
415 smfs->mark_streaming_write_completed ();
423 error << "Corrupt MIDI file " << source->file_path() << endl;
428 remove_file_source (boost::shared_ptr<Source> source)
430 ::unlink (source->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_audiofiles (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;
446 status.sources.clear ();
448 for (vector<Glib::ustring>::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;
478 vector<string> new_paths = get_paths_for_new_sources (status.replace_existing_source, *p,
479 get_best_session_directory_for_new_source (),
482 framepos_t natural_position = source ? source->natural_position() : 0;
484 if (status.replace_existing_source) {
485 fatal << "THIS IS NOT IMPLEMENTED YET, IT SHOULD NEVER GET CALLED!!! DYING!" << endmsg;
486 status.cancel = !map_existing_mono_sources (new_paths, *this, frame_rate(), newfiles, this);
488 status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles, natural_position);
491 // copy on cancel/failure so that any files that were created will be removed below
492 std::copy (newfiles.begin(), newfiles.end(), std::back_inserter(all_new_sources));
498 for (Sources::iterator i = newfiles.begin(); i != newfiles.end(); ++i) {
499 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*i)) != 0) {
500 afs->prepare_for_peakfile_writes ();
504 if (source) { // audio
505 status.doing_what = compose_status_message (*p, source->samplerate(),
506 frame_rate(), status.current, status.total);
507 write_audio_data_to_new_files (source.get(), status, newfiles);
508 } else if (smf_reader.get()) { // midi
509 status.doing_what = string_compose(_("Loading MIDI file %1"), *p);
510 write_midi_data_to_new_files (smf_reader.get(), status, newfiles);
517 if (!status.cancel) {
521 now = localtime (&xnow);
522 status.freeze = true;
524 /* flush the final length(s) to the header(s) */
526 for (Sources::iterator x = all_new_sources.begin(); x != all_new_sources.end(); ) {
527 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*x)) != 0) {
528 afs->update_header((*x)->natural_position(), *now, xnow);
529 afs->done_with_peakfile_writes ();
531 /* now that there is data there, requeue the file for analysis */
533 if (Config->get_auto_analyse_audio()) {
534 Analyser::queue_source_for_analysis (boost::static_pointer_cast<Source>(*x), false);
538 /* don't create tracks for empty MIDI sources (channels) */
540 if ((smfs = boost::dynamic_pointer_cast<SMFSource>(*x)) != 0 && smfs->is_empty()) {
541 x = all_new_sources.erase(x);
547 /* save state so that we don't lose these new Sources */
551 std::copy (all_new_sources.begin(), all_new_sources.end(), std::back_inserter(status.sources));
553 // this can throw...but it seems very unlikely
554 std::for_each (all_new_sources.begin(), all_new_sources.end(), remove_file_source);