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 "pbd/gstdio_compat.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;
134 string mchn_name = string_compose ("%1-t%2", basename, n);
135 filepath = new_midi_source_path (mchn_name);
137 filepath = new_midi_source_path (basename);
140 case DataType::AUDIO:
141 filepath = new_audio_source_path (basename, channels, n, false, false);
145 if (filepath.empty()) {
146 error << string_compose (_("Cannot find new filename for imported file %1"), import_file_path) << endmsg;
147 return vector<string>();
150 new_paths.push_back (filepath);
157 map_existing_mono_sources (const vector<string>& new_paths, Session& /*sess*/,
158 uint32_t /*samplerate*/, vector<boost::shared_ptr<Source> >& newfiles, Session *session)
160 for (vector<string>::const_iterator i = new_paths.begin();
161 i != new_paths.end(); ++i)
163 boost::shared_ptr<Source> source = session->audio_source_by_path_and_channel(*i, 0);
166 error << string_compose(_("Could not find a source for %1 even though we are updating this file!"), (*i)) << endl;
170 newfiles.push_back(boost::dynamic_pointer_cast<Source>(source));
176 create_mono_sources_for_writing (const vector<string>& new_paths,
177 Session& sess, uint32_t samplerate,
178 vector<boost::shared_ptr<Source> >& newfiles,
179 framepos_t timeline_position)
181 for (vector<string>::const_iterator i = new_paths.begin(); i != new_paths.end(); ++i) {
183 boost::shared_ptr<Source> source;
186 const DataType type = SMFSource::safe_midi_file_extension (*i) ? DataType::MIDI : DataType::AUDIO;
188 source = SourceFactory::createWritable (type, sess,
190 false, // destructive
194 catch (const failed_constructor& err) {
195 error << string_compose (_("Unable to create file %1 during import"), *i) << endmsg;
199 newfiles.push_back(boost::dynamic_pointer_cast<Source>(source));
201 /* for audio files, reset the timeline position so that any BWF-ish
202 information in the original files we are importing from is maintained.
205 boost::shared_ptr<AudioFileSource> afs;
206 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
207 afs->set_timeline_position(timeline_position);
214 compose_status_message (const string& path,
215 uint32_t file_samplerate,
216 uint32_t session_samplerate,
217 uint32_t /* current_file */,
218 uint32_t /* total_files */)
220 if (file_samplerate != session_samplerate) {
221 return string_compose (_("Resampling %1 from %2kHz to %3kHz"),
222 Glib::path_get_basename (path),
223 file_samplerate/1000.0f,
224 session_samplerate/1000.0f);
227 return string_compose (_("Copying %1"), Glib::path_get_basename (path));
231 write_audio_data_to_new_files (ImportableSource* source, ImportStatus& status,
232 vector<boost::shared_ptr<Source> >& newfiles)
234 const framecnt_t nframes = ResampledImportableSource::blocksize;
235 boost::shared_ptr<AudioFileSource> afs;
236 uint32_t channels = source->channels();
241 boost::scoped_array<float> data(new float[nframes * channels]);
242 vector<boost::shared_array<Sample> > channel_data;
244 for (uint32_t n = 0; n < channels; ++n) {
245 channel_data.push_back(boost::shared_array<Sample>(new Sample[nframes]));
250 boost::shared_ptr<AudioSource> s = boost::dynamic_pointer_cast<AudioSource> (newfiles[0]);
253 status.progress = 0.0f;
254 float progress_multiplier = 1;
255 float progress_base = 0;
257 if (!source->clamped_at_unity() && s->clamped_at_unity()) {
259 /* The source we are importing from can return sample values with a magnitude greater than 1,
260 and the file we are writing the imported data to cannot handle such values. Compute the gain
261 factor required to normalize the input sources to have a magnitude of less than 1.
265 uint32_t read_count = 0;
267 while (!status.cancel) {
268 framecnt_t const nread = source->read (data.get(), nframes * channels);
273 peak = compute_peak (data.get(), nread * channels, peak);
275 read_count += nread / channels;
276 status.progress = 0.5 * read_count / (source->ratio() * source->length() * channels);
280 /* we are out of range: compute a gain to fix it */
281 gain = (1 - FLT_EPSILON) / peak;
285 progress_multiplier = 0.5;
289 framecnt_t read_count = 0;
291 while (!status.cancel) {
293 framecnt_t nread, nfread;
297 if ((nread = source->read (data.get(), nframes * channels)) == 0) {
298 #ifdef PLATFORM_WINDOWS
299 /* Flush the data once we've finished importing the file. Windows can */
300 /* cache the data for very long periods of time (perhaps not writing */
301 /* it to disk until Ardour closes). So let's force it to flush now. */
302 for (chn = 0; chn < channels; ++chn)
303 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(newfiles[chn])) != 0)
310 /* here is the gain fix for out-of-range sample values that we computed earlier */
311 apply_gain_to_buffer (data.get(), nread, gain);
314 nfread = nread / channels;
318 for (chn = 0; chn < channels; ++chn) {
321 for (x = chn, n = 0; n < nfread; x += channels, ++n) {
322 channel_data[chn][n] = (Sample) data[x];
328 for (chn = 0; chn < channels; ++chn) {
329 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(newfiles[chn])) != 0) {
330 afs->write (channel_data[chn].get(), nfread);
335 status.progress = progress_base + progress_multiplier * read_count / (source->ratio () * source->length() * channels);
340 write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
341 vector<boost::shared_ptr<Source> >& newfiles,
344 uint32_t buf_size = 4;
345 uint8_t* buf = (uint8_t*) malloc (buf_size);
347 status.progress = 0.0f;
349 bool type0 = source->is_type0 () && split_type0;
350 const std::set<uint8_t>& chn = source->channels ();
353 num_tracks = source->channels().size();
355 num_tracks = source->num_tracks();
357 assert (newfiles.size() == num_tracks);
360 vector<boost::shared_ptr<Source> >::iterator s = newfiles.begin();
361 std::set<uint8_t>::const_iterator cur_chan = chn.begin();
363 for (unsigned i = 1; i <= num_tracks; ++i) {
365 boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource> (*s);
367 Glib::Threads::Mutex::Lock source_lock(smfs->mutex());
369 smfs->drop_model (source_lock);
371 source->seek_to_start ();
373 source->seek_to_track (i);
377 uint32_t delta_t = 0;
381 while (!status.cancel) {
382 gint note_id_ignored; // imported files either don't have NoteID's or we ignore them.
386 int ret = source->read_event (&delta_t, &size, &buf, ¬e_id_ignored);
388 if (size > buf_size) {
392 if (ret < 0) { // EOT
398 if (ret == 0) { // Meta
402 // type-0 files separate by channel
404 uint8_t type = buf[0] & 0xf0;
405 uint8_t chan = buf[0] & 0x0f;
406 if (type >= 0x80 && type <= 0xE0) {
407 if (chan != *cur_chan) {
414 smfs->mark_streaming_write_started (source_lock);
418 smfs->append_event_beats(
420 Evoral::Event<Evoral::Beats>(
422 Evoral::Beats::ticks_at_rate(t, source->ppqn()),
426 if (status.progress < 0.99) {
427 status.progress += 0.01;
433 /* we wrote something */
435 const framepos_t pos = 0;
436 const Evoral::Beats length_beats = Evoral::Beats::ticks_at_rate(t, source->ppqn());
437 BeatsFramesConverter converter(smfs->session().tempo_map(), pos);
438 smfs->update_length(pos + converter.to(length_beats.round_up_to_beat()));
439 smfs->mark_streaming_write_completed (source_lock);
445 info << string_compose (_("Track %1 of %2 contained no usable MIDI data"), i, num_tracks) << endmsg;
454 } catch (exception& e) {
455 error << string_compose (_("MIDI file could not be written (best guess: %1)"), e.what()) << endmsg;
464 remove_file_source (boost::shared_ptr<Source> source)
466 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (source);
468 fs->DropReferences ();
471 ::g_unlink (fs->path().c_str());
475 // This function is still unable to cleanly update an existing source, even though
476 // it is possible to set the ImportStatus flag accordingly. The functinality
477 // is disabled at the GUI until the Source implementations are able to provide
478 // the necessary API.
480 Session::import_files (ImportStatus& status)
482 typedef vector<boost::shared_ptr<Source> > Sources;
483 Sources all_new_sources;
484 boost::shared_ptr<AudioFileSource> afs;
485 boost::shared_ptr<SMFSource> smfs;
486 uint32_t channels = 0;
488 status.sources.clear ();
490 for (vector<string>::const_iterator p = status.paths.begin();
491 p != status.paths.end() && !status.cancel;
494 boost::shared_ptr<ImportableSource> source;
495 std::auto_ptr<Evoral::SMF> smf_reader;
496 const DataType type = SMFSource::safe_midi_file_extension (*p) ? DataType::MIDI : DataType::AUDIO;
498 if (type == DataType::AUDIO) {
500 source = open_importable_source (*p, frame_rate(), status.quality);
501 channels = source->channels();
502 } catch (const failed_constructor& err) {
503 error << string_compose(_("Import: cannot open input sound file \"%1\""), (*p)) << endmsg;
504 status.done = status.cancel = true;
510 smf_reader = std::auto_ptr<Evoral::SMF>(new Evoral::SMF());
511 smf_reader->open(*p);
513 if (smf_reader->is_type0 () && status.split_midi_channels) {
514 channels = smf_reader->channels().size();
516 channels = smf_reader->num_tracks();
519 error << _("Import: error opening MIDI file") << endmsg;
520 status.done = status.cancel = true;
526 error << _("Import: file contains no channels.") << endmsg;
530 vector<string> new_paths = get_paths_for_new_sources (status.replace_existing_source, *p, channels);
532 framepos_t natural_position = source ? source->natural_position() : 0;
535 if (status.replace_existing_source) {
536 fatal << "THIS IS NOT IMPLEMENTED YET, IT SHOULD NEVER GET CALLED!!! DYING!" << endmsg;
537 status.cancel = !map_existing_mono_sources (new_paths, *this, frame_rate(), newfiles, this);
539 status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles, natural_position);
542 // copy on cancel/failure so that any files that were created will be removed below
543 std::copy (newfiles.begin(), newfiles.end(), std::back_inserter(all_new_sources));
549 for (Sources::iterator i = newfiles.begin(); i != newfiles.end(); ++i) {
550 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*i)) != 0) {
551 afs->prepare_for_peakfile_writes ();
555 if (source) { // audio
556 status.doing_what = compose_status_message (*p, source->samplerate(),
557 frame_rate(), status.current, status.total);
558 write_audio_data_to_new_files (source.get(), status, newfiles);
559 } else if (smf_reader.get()) { // midi
560 status.doing_what = string_compose(_("Loading MIDI file %1"), *p);
561 write_midi_data_to_new_files (smf_reader.get(), status, newfiles, status.split_midi_channels);
568 if (!status.cancel) {
572 now = localtime (&xnow);
573 status.freeze = true;
575 /* flush the final length(s) to the header(s) */
577 for (Sources::iterator x = all_new_sources.begin(); x != all_new_sources.end(); ) {
579 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*x)) != 0) {
580 afs->update_header((*x)->natural_position(), *now, xnow);
581 afs->done_with_peakfile_writes ();
583 /* now that there is data there, requeue the file for analysis */
585 if (Config->get_auto_analyse_audio()) {
586 Analyser::queue_source_for_analysis (boost::static_pointer_cast<Source>(*x), false);
590 /* imported, copied files cannot be written or removed
593 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource>(*x);
595 /* Only audio files should be marked as
596 immutable - we may need to rewrite MIDI
599 if (boost::dynamic_pointer_cast<AudioFileSource> (fs)) {
600 fs->mark_immutable ();
602 fs->mark_immutable_except_write ();
604 fs->mark_nonremovable ();
607 /* don't create tracks for empty MIDI sources (channels) */
609 if ((smfs = boost::dynamic_pointer_cast<SMFSource>(*x)) != 0 && smfs->is_empty()) {
610 x = all_new_sources.erase(x);
616 /* save state so that we don't lose these new Sources */
620 std::copy (all_new_sources.begin(), all_new_sources.end(), std::back_inserter(status.sources));
623 std::for_each (all_new_sources.begin(), all_new_sources.end(), remove_file_source);
625 error << _("Failed to remove some files after failed/cancelled import operation") << endmsg;