diff options
-rw-r--r-- | gtk2_ardour/editor.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor_audio_import.cc | 28 | ||||
-rw-r--r-- | gtk2_ardour/editor_region_list.cc | 18 | ||||
-rw-r--r-- | gtk2_ardour/sfdb_ui.cc | 37 | ||||
-rw-r--r-- | gtk2_ardour/sfdb_ui.h | 6 | ||||
-rw-r--r-- | libs/ardour/SConscript | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/importable_source.h | 48 | ||||
-rw-r--r-- | libs/ardour/ardour/resampled_source.h | 49 | ||||
-rw-r--r-- | libs/ardour/ardour/utils.h | 2 | ||||
-rw-r--r-- | libs/ardour/import.cc | 129 | ||||
-rw-r--r-- | libs/ardour/resampled_source.cc | 108 | ||||
-rw-r--r-- | libs/ardour/utils.cc | 13 |
12 files changed, 300 insertions, 141 deletions
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 0b7e0c4a4c..b48dce0ce1 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -981,7 +981,7 @@ class Editor : public PublicEditor nframes64_t& pos, int target_regions, int target_tracks, boost::shared_ptr<ARDOUR::AudioTrack>&); int add_sources (vector<Glib::ustring> paths, ARDOUR::SourceList& sources, nframes64_t& pos, Editing::ImportMode, - int target_regions, int target_tracks, boost::shared_ptr<ARDOUR::AudioTrack>&); + int target_regions, int target_tracks, boost::shared_ptr<ARDOUR::AudioTrack>&, bool add_channel_suffix); int finish_bringing_in_audio (boost::shared_ptr<ARDOUR::AudioRegion> region, uint32_t, uint32_t, nframes64_t& pos, Editing::ImportMode mode, boost::shared_ptr<ARDOUR::AudioTrack>& existing_track); diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc index 11896fbba8..8f47215c8e 100644 --- a/gtk2_ardour/editor_audio_import.cc +++ b/gtk2_ardour/editor_audio_import.cc @@ -367,7 +367,7 @@ Editor::import_sndfiles (vector<ustring> paths, ImportMode mode, nframes64_t& po goto out; } - if (add_sources (paths, import_status.sources, pos, mode, target_regions, target_tracks, track) == 0) { + if (add_sources (paths, import_status.sources, pos, mode, target_regions, target_tracks, track, false) == 0) { session->save_state (""); } @@ -523,7 +523,7 @@ Editor::embed_sndfiles (vector<Glib::ustring> paths, bool multifile, goto out; } - ret = add_sources (paths, sources, pos, mode, target_regions, target_tracks, track); + ret = add_sources (paths, sources, pos, mode, target_regions, target_tracks, track, true); out: track_canvas.get_window()->set_cursor (*current_canvas_cursor); @@ -532,7 +532,7 @@ Editor::embed_sndfiles (vector<Glib::ustring> paths, bool multifile, int Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64_t& pos, ImportMode mode, - int target_regions, int target_tracks, boost::shared_ptr<AudioTrack>& track) + int target_regions, int target_tracks, boost::shared_ptr<AudioTrack>& track, bool add_channel_suffix) { vector<boost::shared_ptr<AudioRegion> > regions; ustring region_name; @@ -552,7 +552,7 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64 /* take all the sources we have and package them up as a region */ - region_name = region_name_from_path (paths.front(), (sources.size() > 1)); + region_name = region_name_from_path (paths.front(), (sources.size() > 1), false); regions.push_back (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, 0, sources[0]->length(), region_name, 0, @@ -564,15 +564,18 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64 SourceList just_one; SourceList::iterator x; + uint32_t n; - for (x = sources.begin(); x != sources.end(); ++x) { + for (n = 0, x = sources.begin(); x != sources.end(); ++x, ++n) { just_one.clear (); just_one.push_back (*x); - + boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*x); - region_name = region_name_from_path (afs->path(), false); + region_name = region_name_from_path (afs->path(), false, true, sources.size(), n); + + cerr << "got region name " << region_name << endl; regions.push_back (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (just_one, 0, (*x)->length(), region_name, 0, @@ -597,10 +600,12 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64 output_chan = input_chan; } - for (vector<boost::shared_ptr<AudioRegion> >::iterator r = regions.begin(); r != regions.end(); ++r) { + int n = 0; - finish_bringing_in_audio (*r, input_chan, output_chan, pos, mode, track); + for (vector<boost::shared_ptr<AudioRegion> >::iterator r = regions.begin(); r != regions.end(); ++r, ++n) { + finish_bringing_in_audio (*r, input_chan, output_chan, pos, mode, track); + if (target_tracks != 1) { track.reset (); } else { @@ -652,12 +657,15 @@ Editor::finish_bringing_in_audio (boost::shared_ptr<AudioRegion> region, uint32_ { if (!existing_track) { list<boost::shared_ptr<AudioTrack> > at (session->new_audio_track (in_chans, out_chans, Normal, 1)); + if (at.empty()) { return -1; } + existing_track = at.front(); - existing_track->set_name (basename_nosuffix (region->name()), this); + existing_track->set_name (region->name(), this); } + boost::shared_ptr<AudioRegion> copy (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (region))); existing_track->diskstream()->playlist()->add_region (copy, pos); break; diff --git a/gtk2_ardour/editor_region_list.cc b/gtk2_ardour/editor_region_list.cc index 55e668eb00..b59b7ff583 100644 --- a/gtk2_ardour/editor_region_list.cc +++ b/gtk2_ardour/editor_region_list.cc @@ -134,21 +134,11 @@ Editor::add_audio_region_to_region_display (boost::shared_ptr<AudioRegion> regio if (region->source()->name()[0] == '/') { // external file - if (region->whole_file()) { - - boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(region->source()); - - str = ".../"; - - if (afs) { - str = region_name_from_path (afs->path(), region->n_channels() > 1); - } else { - str += region->source()->name(); - } + /* XXX there was old code here to try to show an abbreviated version + of the path name for whole file regions. + */ - } else { - str = region->name(); - } + str = region->name(); } else { diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc index e354b4ec01..46cd2ed9b4 100644 --- a/gtk2_ardour/sfdb_ui.cc +++ b/gtk2_ardour/sfdb_ui.cc @@ -65,8 +65,8 @@ ustring SoundFileBrowser::persistent_folder; SoundFileBox::SoundFileBox () : _session(0), table (6, 2), - length_clock ("sfboxLengthClock", true, "EditCursorClock", false, true, false), - timecode_clock ("sfboxTimecodeClock", true, "EditCursorClock", false, false, false), + length_clock ("sfboxLengthClock", false, "EditCursorClock", false, true, false), + timecode_clock ("sfboxTimecodeClock", false, "EditCursorClock", false, false, false), main_box (false, 6), autoplay_btn (_("Auto-play")) @@ -110,7 +110,7 @@ SoundFileBox::SoundFileBox () table.attach (length_clock, 1, 2, 4, 5, FILL, (AttachOptions) 0); table.attach (timecode_clock, 1, 2, 5, 6, FILL, (AttachOptions) 0); - length_clock.set_mode (AudioClock::MinSec); + length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock.mode()); timecode_clock.set_mode (AudioClock::SMPTE); hbox = manage (new HBox); @@ -204,7 +204,18 @@ SoundFileBox::setup_labels (const ustring& filename) preview_label.set_markup (string_compose ("<b>%1</b>", Glib::path_get_basename (filename))); format_text.set_text (sf_info.format_name); channels_value.set_text (to_string (sf_info.channels, std::dec)); - samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate)); + + if (_session && sf_info.samplerate != _session->frame_rate()) { + samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:"))); + samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate)); + samplerate_value.set_name ("NewSessionSR1Label"); + samplerate.set_name ("NewSessionSR1Label"); + } else { + samplerate.set_text (_("Sample rate:")); + samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate)); + samplerate_value.set_name ("NewSessionSR2Label"); + samplerate.set_name ("NewSessionSR2Label"); + } length_clock.set (sf_info.length, true); timecode_clock.set (sf_info.timecode, true); @@ -781,6 +792,15 @@ SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::S found_list_view.get_selection()->set_mode (SELECTION_SINGLE); } +void +SoundFileChooser::on_hide () +{ + ArdourDialog::on_hide(); + if (session) { + session->cancel_audition(); + } +} + ustring SoundFileChooser::get_filename () { @@ -903,6 +923,15 @@ SoundFileOmega::get_mode () const } } +void +SoundFileOmega::on_hide () +{ + ArdourDialog::on_hide(); + if (session) { + session->cancel_audition(); + } +} + ImportPosition SoundFileOmega::get_position() const { diff --git a/gtk2_ardour/sfdb_ui.h b/gtk2_ardour/sfdb_ui.h index 66d4aa4173..4670796700 100644 --- a/gtk2_ardour/sfdb_ui.h +++ b/gtk2_ardour/sfdb_ui.h @@ -158,6 +158,9 @@ class SoundFileChooser : public SoundFileBrowser Glib::ustring get_filename (); + protected: + void on_hide(); + private: // SoundFileBrowser browser; }; @@ -180,6 +183,9 @@ class SoundFileOmega : public SoundFileBrowser Editing::ImportPosition get_position() const; Editing::ImportDisposition get_channel_disposition() const; + protected: + void on_hide(); + private: uint32_t selected_track_cnt; diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index 53fd746273..309357cb1b 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -71,6 +71,7 @@ recent_sessions.cc redirect.cc region.cc region_factory.cc +resampled_source.cc reverse.cc route.cc route_group.cc diff --git a/libs/ardour/ardour/importable_source.h b/libs/ardour/ardour/importable_source.h new file mode 100644 index 0000000000..29742d1076 --- /dev/null +++ b/libs/ardour/ardour/importable_source.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2007 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_importable_source_h__ +#define __ardour_importable_source_h__ + +#include <sndfile.h> +#include <ardour/types.h> + +namespace ARDOUR { + +class ImportableSource { + public: + ImportableSource (SNDFILE* sf, SF_INFO* info) : in (sf), sf_info (info) {} + virtual ~ImportableSource() {} + + virtual nframes_t read (Sample* buffer, nframes_t nframes) { + nframes_t per_channel = nframes / sf_info->channels; + per_channel = sf_readf_float (in, buffer, per_channel); + return per_channel * sf_info->channels; + } + + virtual float ratio() const { return 1.0f; } + +protected: + SNDFILE* in; + SF_INFO* sf_info; +}; + +} + +#endif /* __ardour_importable_source_h__ */ diff --git a/libs/ardour/ardour/resampled_source.h b/libs/ardour/ardour/resampled_source.h new file mode 100644 index 0000000000..af7b4a07fe --- /dev/null +++ b/libs/ardour/ardour/resampled_source.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2007 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_resampled_source_h__ +#define __ardour_resampled_source_h__ + +#include <samplerate.h> + +#include <ardour/importable_source.h> + +namespace ARDOUR { + +class ResampledImportableSource : public ImportableSource +{ + public: + ResampledImportableSource (SNDFILE* sf, SF_INFO* info, nframes_t rate); + ~ResampledImportableSource (); + + nframes_t read (Sample* buffer, nframes_t nframes); + + float ratio() const { return src_data.src_ratio; } + + static const uint32_t blocksize; + + private: + float* input; + SRC_STATE* src_state; + SRC_DATA src_data; +}; + +} + +#endif /* __ardour_resampled_source_h__ */ diff --git a/libs/ardour/ardour/utils.h b/libs/ardour/ardour/utils.h index 20badf5ea1..0d4ce08adc 100644 --- a/libs/ardour/ardour/utils.h +++ b/libs/ardour/ardour/utils.h @@ -53,7 +53,7 @@ int tokenize_fullpath (std::string fullpath, std::string& path, std::string& nam int touch_file(Glib::ustring path); Glib::ustring path_expand (Glib::ustring); -Glib::ustring region_name_from_path (Glib::ustring path, bool strip_channels); +Glib::ustring region_name_from_path (Glib::ustring path, bool strip_channels, bool add_channel_suffix = false, uint32_t total = 0, uint32_t this_one = 0); bool path_is_paired (Glib::ustring path, Glib::ustring& pair_base); void compute_equal_power_fades (nframes_t nframes, float* in, float* out); diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc index c9b303f007..166093ba1e 100644 --- a/libs/ardour/import.cc +++ b/libs/ardour/import.cc @@ -32,6 +32,7 @@ #include <glibmm.h> #include <pbd/basename.h> +#include <pbd/convert.h> #include <ardour/ardour.h> #include <ardour/session.h> @@ -41,72 +42,13 @@ #include <ardour/audioregion.h> #include <ardour/region_factory.h> #include <ardour/source_factory.h> - +#include <ardour/resampled_source.h> #include "i18n.h" using namespace ARDOUR; using namespace PBD; -#define BLOCKSIZE 4096U - -class ImportableSource { - public: - ImportableSource (SNDFILE* sf, SF_INFO* info) : in (sf), sf_info (info) {} - virtual ~ImportableSource() {} - - virtual nframes_t read (Sample* buffer, nframes_t nframes) { - nframes_t per_channel = nframes / sf_info->channels; - per_channel = sf_readf_float (in, buffer, per_channel); - return per_channel * sf_info->channels; - } - - virtual float ratio() const { return 1.0f; } - -protected: - SNDFILE* in; - SF_INFO* sf_info; -}; - -class ResampledImportableSource : public ImportableSource { - public: - ResampledImportableSource (SNDFILE* sf, SF_INFO* info, nframes_t rate) : ImportableSource (sf, info) { - int err; - - sf_seek (in, 0, SEEK_SET) ; - - /* Initialize the sample rate converter. */ - - if ((src_state = src_new (SRC_SINC_BEST_QUALITY, sf_info->channels, &err)) == 0) { - error << string_compose(_("Import: src_new() failed : %1"), src_strerror (err)) << endmsg ; - throw failed_constructor (); - } - - src_data.end_of_input = 0 ; /* Set this later. */ - - /* Start with zero to force load in while loop. */ - - src_data.input_frames = 0 ; - src_data.data_in = input ; - - src_data.src_ratio = ((float) rate) / sf_info->samplerate ; - - } - - ~ResampledImportableSource () { - src_state = src_delete (src_state) ; - } - - nframes_t read (Sample* buffer, nframes_t nframes); - - float ratio() const { return src_data.src_ratio; } - - private: - float input[BLOCKSIZE]; - SRC_STATE* src_state; - SRC_DATA src_data; -}; - int Session::import_audiofile (import_status& status) { @@ -124,11 +66,12 @@ Session::import_audiofile (import_status& status) vector<string> new_paths; struct tm* now; ImportableSource* importable = 0; - const nframes_t nframes = BLOCKSIZE; + const nframes_t nframes = ResampledImportableSource::blocksize; + uint32_t cnt = 1; status.sources.clear (); - for (vector<Glib::ustring>::iterator p = status.paths.begin(); p != status.paths.end(); ++p) { + for (vector<Glib::ustring>::iterator p = status.paths.begin(); p != status.paths.end(); ++p, ++cnt) { if ((in = sf_open ((*p).c_str(), SFM_READ, &info)) == 0) { error << string_compose(_("Import: cannot open input sound file \"%1\""), (*p)) << endmsg; @@ -207,7 +150,20 @@ Session::import_audiofile (import_status& status) so_far = 0; - status.doing_what = _("converting audio"); + if ((nframes_t) info.samplerate != frame_rate()) { + status.doing_what = string_compose (_("converting %1\n(resample from %2KHz to %3KHz)\n(%4 of %5)"), + basepath, + info.samplerate/1000.0f, + frame_rate()/1000.0f, + cnt, status.paths.size()); + + } else { + status.doing_what = string_compose (_("converting %1\n(%2 of %3)"), + basepath, + cnt, status.paths.size()); + + } + status.progress = 0.0; while (!status.cancel) { @@ -305,50 +261,3 @@ Session::import_audiofile (import_status& status) return ret; } - -nframes_t -ResampledImportableSource::read (Sample* output, nframes_t nframes) -{ - int err; - - /* If the input buffer is empty, refill it. */ - - if (src_data.input_frames == 0) { - - src_data.input_frames = ImportableSource::read (input, BLOCKSIZE); - - /* The last read will not be a full buffer, so set end_of_input. */ - - if ((nframes_t) src_data.input_frames < BLOCKSIZE) { - src_data.end_of_input = SF_TRUE ; - } - - src_data.input_frames /= sf_info->channels; - src_data.data_in = input ; - } - - src_data.data_out = output; - - if (!src_data.end_of_input) { - src_data.output_frames = nframes / sf_info->channels ; - } else { - src_data.output_frames = src_data.input_frames; - } - - if ((err = src_process (src_state, &src_data))) { - error << string_compose(_("Import: %1"), src_strerror (err)) << endmsg ; - return 0 ; - } - - /* Terminate if at end */ - - if (src_data.end_of_input && src_data.output_frames_gen == 0) { - return 0; - } - - src_data.data_in += src_data.input_frames_used * sf_info->channels ; - src_data.input_frames -= src_data.input_frames_used ; - - return src_data.output_frames_gen * sf_info->channels; -} - diff --git a/libs/ardour/resampled_source.cc b/libs/ardour/resampled_source.cc new file mode 100644 index 0000000000..29dab6e0cb --- /dev/null +++ b/libs/ardour/resampled_source.cc @@ -0,0 +1,108 @@ +/* + Copyright (C) 2007 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <pbd/error.h> +#include <ardour/resampled_source.h> +#include <pbd/failed_constructor.h> + +#include "i18n.h" + +using namespace ARDOUR; +using namespace PBD; + +const uint32_t ResampledImportableSource::blocksize = 4096U; + +ResampledImportableSource::ResampledImportableSource (SNDFILE* sf, SF_INFO* info, nframes_t rate) + : ImportableSource (sf, info) +{ + int err; + + sf_seek (in, 0, SEEK_SET) ; + + /* Initialize the sample rate converter. */ + + if ((src_state = src_new (SRC_SINC_BEST_QUALITY, sf_info->channels, &err)) == 0) { + error << string_compose(_("Import: src_new() failed : %1"), src_strerror (err)) << endmsg ; + throw failed_constructor (); + } + + src_data.end_of_input = 0 ; /* Set this later. */ + + /* Start with zero to force load in while loop. */ + + src_data.input_frames = 0 ; + src_data.data_in = input ; + + src_data.src_ratio = ((float) rate) / sf_info->samplerate ; + + input = new float[blocksize]; +} + +ResampledImportableSource::~ResampledImportableSource () +{ + src_state = src_delete (src_state) ; + delete [] input; +} + +nframes_t +ResampledImportableSource::read (Sample* output, nframes_t nframes) +{ + int err; + + /* If the input buffer is empty, refill it. */ + + if (src_data.input_frames == 0) { + + src_data.input_frames = ImportableSource::read (input, blocksize); + + /* The last read will not be a full buffer, so set end_of_input. */ + + if ((nframes_t) src_data.input_frames < blocksize) { + src_data.end_of_input = SF_TRUE ; + } + + src_data.input_frames /= sf_info->channels; + src_data.data_in = input ; + } + + src_data.data_out = output; + + if (!src_data.end_of_input) { + src_data.output_frames = nframes / sf_info->channels ; + } else { + src_data.output_frames = src_data.input_frames; + } + + if ((err = src_process (src_state, &src_data))) { + error << string_compose(_("Import: %1"), src_strerror (err)) << endmsg ; + return 0 ; + } + + /* Terminate if at end */ + + if (src_data.end_of_input && src_data.output_frames_gen == 0) { + return 0; + } + + src_data.data_in += src_data.input_frames_used * sf_info->channels ; + src_data.input_frames -= src_data.input_frames_used ; + + return src_data.output_frames_gen * sf_info->channels; +} + diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc index 6b5ea2cef6..e34fdd75a1 100644 --- a/libs/ardour/utils.cc +++ b/libs/ardour/utils.cc @@ -208,7 +208,7 @@ touch_file (ustring path) } ustring -region_name_from_path (ustring path, bool strip_channels) +region_name_from_path (ustring path, bool strip_channels, bool add_channel_suffix, uint32_t total, uint32_t this_one) { path = PBD::basename_nosuffix (path); @@ -225,6 +225,17 @@ region_name_from_path (ustring path, bool strip_channels) } } + if (add_channel_suffix) { + + path += '%'; + + if (total > 2) { + path += (char) ('a' + this_one); + } else { + path += (char) (this_one == 0 ? 'L' : 'R'); + } + } + return path; } |