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 (HeaderFormat hf
, 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 string ext
= native_header_format_extension (hf
, type
);
129 if (type
== DataType::AUDIO
&& channels
== 2) {
131 snprintf (buf
, sizeof(buf
), "%s-L%s", base
.c_str(), ext
.c_str());
133 snprintf (buf
, sizeof(buf
), "%s-R%s", base
.c_str(), ext
.c_str());
135 } else if (channels
> 1) {
136 snprintf (buf
, sizeof(buf
), "%s-c%d%s", base
.c_str(), channel
, ext
.c_str());
138 snprintf (buf
, sizeof(buf
), "%s%s", base
.c_str(), ext
.c_str());
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 (HeaderFormat hf
, 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 (hf
, 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
) {
381 gint ignored
; // imported files either don't have NoteID's or
386 int ret
= source
->read_event(&delta_t
, &size
, &buf
, &ignored
);
390 if (ret
< 0) { // EOT
396 if (ret
== 0) { // Meta
401 smfs
->mark_streaming_write_started ();
405 smfs
->append_event_unlocked_beats(Evoral::Event
<double>(0,
406 (double)t
/ (double)source
->ppqn(),
410 if (status
.progress
< 0.99)
411 status
.progress
+= 0.01;
414 const nframes64_t pos
= 0;
415 const double length_beats
= ceil(t
/ (double)source
->ppqn());
416 BeatsFramesConverter
converter(smfs
->session().tempo_map(), pos
);
417 smfs
->update_length(pos
, converter
.to(length_beats
));
418 smfs
->mark_streaming_write_completed ();
426 error
<< "Corrupt MIDI file " << source
->file_path() << endl
;
431 remove_file_source (boost::shared_ptr
<Source
> source
)
433 ::unlink (source
->path().c_str());
436 // This function is still unable to cleanly update an existing source, even though
437 // it is possible to set the ImportStatus flag accordingly. The functinality
438 // is disabled at the GUI until the Source implementations are able to provide
439 // the necessary API.
441 Session::import_audiofiles (ImportStatus
& status
)
443 typedef vector
<boost::shared_ptr
<Source
> > Sources
;
444 Sources all_new_sources
;
445 boost::shared_ptr
<AudioFileSource
> afs
;
446 boost::shared_ptr
<SMFSource
> smfs
;
449 status
.sources
.clear ();
451 for (vector
<Glib::ustring
>::iterator p
= status
.paths
.begin();
452 p
!= status
.paths
.end() && !status
.cancel
;
455 boost::shared_ptr
<ImportableSource
> source
;
456 std::auto_ptr
<Evoral::SMF
> smf_reader
;
457 const DataType type
= SMFSource::safe_midi_file_extension (*p
) ? DataType::MIDI
: DataType::AUDIO
;
459 if (type
== DataType::AUDIO
) {
461 source
= open_importable_source (*p
, frame_rate(), status
.quality
);
462 channels
= source
->channels();
463 } catch (const failed_constructor
& err
) {
464 error
<< string_compose(_("Import: cannot open input sound file \"%1\""), (*p
)) << endmsg
;
465 status
.done
= status
.cancel
= true;
471 smf_reader
= std::auto_ptr
<Evoral::SMF
>(new Evoral::SMF());
472 smf_reader
->open(*p
);
473 channels
= smf_reader
->num_tracks();
475 error
<< _("Import: error opening MIDI file") << endmsg
;
476 status
.done
= status
.cancel
= true;
481 vector
<string
> new_paths
= get_paths_for_new_sources (config
.get_native_file_header_format(),
482 status
.replace_existing_source
, *p
,
483 get_best_session_directory_for_new_source (),
486 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(); ) {
531 if ((afs
= boost::dynamic_pointer_cast
<AudioFileSource
>(*x
)) != 0) {
532 afs
->update_header((*x
)->natural_position(), *now
, xnow
);
533 afs
->done_with_peakfile_writes ();
535 /* now that there is data there, requeue the file for analysis */
537 if (Config
->get_auto_analyse_audio()) {
538 Analyser::queue_source_for_analysis (boost::static_pointer_cast
<Source
>(*x
), false);
542 /* don't create tracks for empty MIDI sources (channels) */
544 if ((smfs
= boost::dynamic_pointer_cast
<SMFSource
>(*x
)) != 0 && smfs
->is_empty()) {
545 x
= all_new_sources
.erase(x
);
551 /* save state so that we don't lose these new Sources */
555 std::copy (all_new_sources
.begin(), all_new_sources
.end(), std::back_inserter(status
.sources
));
557 // this can throw...but it seems very unlikely
558 std::for_each (all_new_sources
.begin(), all_new_sources
.end(), remove_file_source
);