diff options
Diffstat (limited to 'libs')
-rw-r--r-- | libs/ardour/SConscript | 7 | ||||
-rw-r--r-- | libs/ardour/ardour/beats_frames_converter.h | 52 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_source.h | 21 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 6 | ||||
-rw-r--r-- | libs/ardour/audio_region_importer.cc | 2 | ||||
-rw-r--r-- | libs/ardour/beats_frames_converter.cc | 54 | ||||
-rw-r--r-- | libs/ardour/import.cc | 24 | ||||
-rw-r--r-- | libs/ardour/midi_source.cc | 22 | ||||
-rw-r--r-- | libs/ardour/quantize.cc | 13 | ||||
-rw-r--r-- | libs/ardour/smf_source.cc | 29 | ||||
-rw-r--r-- | libs/evoral/evoral/TimeConverter.hpp | 43 |
11 files changed, 203 insertions, 70 deletions
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index 11a5b36566..83b7d659b5 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -38,6 +38,7 @@ audio_library.cc audio_playlist.cc audio_playlist_importer.cc audio_port.cc +audio_region_importer.cc audio_track.cc audio_track_importer.cc audioanalyser.cc @@ -45,13 +46,13 @@ audioengine.cc audiofile_tagger.cc audiofilesource.cc audioregion.cc -audio_region_importer.cc audiosource.cc auditioner.cc automatable.cc automation.cc automation_control.cc automation_list.cc +beats_frames_converter.cc broadcast_info.cc buffer.cc buffer_set.cc @@ -65,8 +66,8 @@ cycle_timer.cc default_click.cc directory_names.cc diskstream.cc -element_importer.cc element_import_handler.cc +element_importer.cc enums.cc event_type_map.cc export_channel.cc @@ -162,8 +163,8 @@ svn_revision.cc tape_file_matcher.cc template_utils.cc tempo.cc -ticker.cc tempo_map_importer.cc +ticker.cc track.cc transient_detector.cc user_bundle.cc diff --git a/libs/ardour/ardour/beats_frames_converter.h b/libs/ardour/ardour/beats_frames_converter.h new file mode 100644 index 0000000000..79972cb4c5 --- /dev/null +++ b/libs/ardour/ardour/beats_frames_converter.h @@ -0,0 +1,52 @@ +/* + Copyright (C) 2009 Paul Davis + Author: Dave Robillard + + 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. + + $Id: midiregion.h 733 2006-08-01 17:19:38Z drobilla $ +*/ + +#include <evoral/TimeConverter.hpp> +#include <ardour/types.h> + +#ifndef __ardour_beats_frames_converter_h__ +#define __ardour_beats_frames_converter_h__ + +namespace ARDOUR { + +class Session; + +class BeatsFramesConverter : public Evoral::TimeConverter<double,nframes_t> { +public: + BeatsFramesConverter(Session& session, nframes_t origin) + : _session(session) + , _origin(origin) + {} + + nframes_t to(double beats) const; + double from(nframes_t frames) const; + + nframes_t origin() const { return _origin; } + void set_origin(nframes_t origin) { _origin = origin; } + +private: + Session& _session; + nframes_t _origin; +}; + +} /* namespace ARDOUR */ + +#endif /* __ardour_beats_frames_converter_h__ */ diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h index 3f8ed82310..3a28cde8c6 100644 --- a/libs/ardour/ardour/midi_source.h +++ b/libs/ardour/ardour/midi_source.h @@ -30,8 +30,7 @@ #include <ardour/ardour.h> #include <ardour/buffer.h> #include <ardour/source.h> - -using std::string; +#include <ardour/beats_frames_converter.h> namespace ARDOUR { @@ -44,7 +43,7 @@ class MidiSource : public Source public: typedef double TimeType; - MidiSource (Session& session, string name); + MidiSource (Session& session, std::string name); MidiSource (Session& session, const XMLNode&); virtual ~MidiSource (); @@ -66,13 +65,13 @@ class MidiSource : public Source virtual void mark_streaming_write_started (); virtual void mark_streaming_write_completed (); - uint64_t timeline_position () { return _timeline_position; } - void set_timeline_position (nframes_t when) { _timeline_position = when; } + uint64_t timeline_position () { return _timeline_position; } + void set_timeline_position (nframes_t when); virtual void session_saved(); - string captured_for() const { return _captured_for; } - void set_captured_for (string str) { _captured_for = str; } + std::string captured_for() const { return _captured_for; } + void set_captured_for (std::string str) { _captured_for = str; } uint32_t read_data_count() const { return _read_data_count; } uint32_t write_data_count() const { return _write_data_count; } @@ -96,6 +95,8 @@ class MidiSource : public Source void set_model(boost::shared_ptr<MidiModel> m) { _model = m; } void drop_model() { _model.reset(); } + BeatsFramesConverter& converter() { return _converter; } + protected: virtual void flush_midi() = 0; @@ -104,10 +105,12 @@ class MidiSource : public Source virtual nframes_t write_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t cnt) = 0; mutable Glib::Mutex _lock; - string _captured_for; + std::string _captured_for; uint64_t _timeline_position; mutable uint32_t _read_data_count; ///< modified in read() mutable uint32_t _write_data_count; ///< modified in write() + + BeatsFramesConverter _converter; boost::shared_ptr<MidiModel> _model; bool _writing; @@ -116,7 +119,7 @@ class MidiSource : public Source mutable nframes_t _last_read_end; private: - bool file_changed (string path); + bool file_changed (std::string path); }; } diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 8de0e1c523..ef25ebaea3 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -610,7 +610,7 @@ class Session : public PBD::StatefulDestructible /* source management */ - struct import_status : public InterThreadInfo { + struct ImportStatus : public InterThreadInfo { string doing_what; /* control info */ @@ -624,8 +624,8 @@ class Session : public PBD::StatefulDestructible SourceList sources; }; - void import_audiofiles (import_status&); - bool sample_rate_convert (import_status&, string infile, string& outfile); + void import_audiofiles (ImportStatus&); + bool sample_rate_convert (ImportStatus&, string infile, string& outfile); string build_tmp_convert_name (string file); boost::shared_ptr<ExportHandler> get_export_handler (); diff --git a/libs/ardour/audio_region_importer.cc b/libs/ardour/audio_region_importer.cc index 714446bfe2..23f3bfd6c6 100644 --- a/libs/ardour/audio_region_importer.cc +++ b/libs/ardour/audio_region_importer.cc @@ -336,7 +336,7 @@ AudioRegionImporter::prepare_sources () return; } - Session::import_status status; + Session::ImportStatus status; // Get sources that still need to be imported for (std::list<string>::iterator it = filenames.begin(); it != filenames.end(); ++it) { diff --git a/libs/ardour/beats_frames_converter.cc b/libs/ardour/beats_frames_converter.cc new file mode 100644 index 0000000000..736068e690 --- /dev/null +++ b/libs/ardour/beats_frames_converter.cc @@ -0,0 +1,54 @@ +/* + Copyright (C) 2009 Paul Davis + Author: Dave Robillard + + 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. + + $Id: midiregion.h 733 2006-08-01 17:19:38Z drobilla $ +*/ + +#include <ardour/audioengine.h> +#include <ardour/beats_frames_converter.h> +#include <ardour/session.h> +#include <ardour/tempo.h> + +namespace ARDOUR { + +nframes_t +BeatsFramesConverter::to(double beats) const +{ + // FIXME: assumes tempo never changes after origin + const Tempo& tempo = _session.tempo_map().tempo_at(_origin); + const double frames_per_beat = tempo.frames_per_beat( + _session.engine().frame_rate(), + _session.tempo_map().meter_at(_origin)); + + return lrint(beats * frames_per_beat); +} + +double +BeatsFramesConverter::from(nframes_t frames) const +{ + // FIXME: assumes tempo never changes after origin + const Tempo& tempo = _session.tempo_map().tempo_at(_origin); + const double frames_per_beat = tempo.frames_per_beat( + _session.engine().frame_rate(), + _session.tempo_map().meter_at(_origin)); + + return frames / frames_per_beat; +} + +} /* namespace ARDOUR */ + diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc index 824cdb43f7..0e2cfb9988 100644 --- a/libs/ardour/import.cc +++ b/libs/ardour/import.cc @@ -257,7 +257,7 @@ compose_status_message (const string& path, } static void -write_audio_data_to_new_files (ImportableSource* source, Session::import_status& status, +write_audio_data_to_new_files (ImportableSource* source, Session::ImportStatus& status, vector<boost::shared_ptr<Source> >& newfiles) { const nframes_t nframes = ResampledImportableSource::blocksize; @@ -309,8 +309,8 @@ write_audio_data_to_new_files (ImportableSource* source, Session::import_status& } static void -write_midi_data_to_new_files (Evoral::SMF* source, Session::import_status& status, - vector<boost::shared_ptr<Source> >& newfiles) +write_midi_data_to_new_files (Evoral::SMF* source, Session::ImportStatus& status, + vector<boost::shared_ptr<Source> >& newfiles) { uint32_t buf_size = 4; uint8_t* buf = (uint8_t*)malloc(buf_size); @@ -354,20 +354,14 @@ write_midi_data_to_new_files (Evoral::SMF* source, Session::import_status& statu if (status.progress < 0.99) status.progress += 0.01; } - - nframes_t timeline_position = 0; // FIXME: ? - // FIXME: kluuuuudge: assumes tempo never changes after start - const double frames_per_beat = smfs->session().tempo_map().tempo_at( - timeline_position).frames_per_beat( - smfs->session().engine().frame_rate(), - smfs->session().tempo_map().meter_at(timeline_position)); - - smfs->update_length(0, (nframes_t) ceil ((t / (double)source->ppqn()) * frames_per_beat)); + const double length_beats = ceil(t / (double)source->ppqn()); + smfs->update_length(0, smfs->converter().to(length_beats)); smfs->end_write(); - if (status.cancel) + if (status.cancel) { break; + } } } catch (...) { @@ -382,11 +376,11 @@ remove_file_source (boost::shared_ptr<Source> source) } // This function is still unable to cleanly update an existing source, even though -// it is possible to set the import_status flag accordingly. The functinality +// it is possible to set the ImportStatus flag accordingly. The functinality // is disabled at the GUI until the Source implementations are able to provide // the necessary API. void -Session::import_audiofiles (import_status& status) +Session::import_audiofiles (ImportStatus& status) { uint32_t cnt = 1; typedef vector<boost::shared_ptr<Source> > Sources; diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index 70abb99e56..ece0d9b104 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -52,16 +52,20 @@ sigc::signal<void,MidiSource *> MidiSource::MidiSourceCreated; MidiSource::MidiSource (Session& s, string name) : Source (s, name, DataType::MIDI) , _timeline_position(0) + , _read_data_count(0) + , _write_data_count(0) + , _converter(s, _timeline_position) , _writing (false) , _last_read_end(0) { - _read_data_count = 0; - _write_data_count = 0; } MidiSource::MidiSource (Session& s, const XMLNode& node) : Source (s, node) , _timeline_position(0) + , _read_data_count(0) + , _write_data_count(0) + , _converter(s, _timeline_position) , _writing (false) , _last_read_end(0) { @@ -110,12 +114,7 @@ MidiSource::midi_read (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_ Glib::Mutex::Lock lm (_lock); if (_model) { - // FIXME: assumes tempo never changes after start - const Tempo& tempo = _session.tempo_map().tempo_at(_timeline_position); - const double frames_per_beat = tempo.frames_per_beat( - _session.engine().frame_rate(), - _session.tempo_map().meter_at(_timeline_position)); -#define BEATS_TO_FRAMES(t) (((t) * frames_per_beat) + stamp_offset - negative_stamp_offset) +#define BEATS_TO_FRAMES(t) (_converter.to(t) + stamp_offset - negative_stamp_offset) Evoral::Sequence<double>::const_iterator& i = _model_iter; @@ -162,6 +161,13 @@ MidiSource::file_changed (string path) } void +MidiSource::set_timeline_position (nframes_t when) +{ + _timeline_position = when; + _converter.set_origin(when); +} + +void MidiSource::mark_streaming_midi_write_started (NoteMode mode, nframes_t start_frame) { set_timeline_position(start_frame); // why do I have a feeling this can break somehow... diff --git a/libs/ardour/quantize.cc b/libs/ardour/quantize.cc index e4a2809277..76eb924612 100644 --- a/libs/ardour/quantize.cc +++ b/libs/ardour/quantize.cc @@ -62,19 +62,12 @@ Quantize::run (boost::shared_ptr<Region> r) boost::shared_ptr<MidiModel> model = src->model(); - // FIXME: Model really needs to be switched to beat time (double) ASAP - - const Tempo& t = session.tempo_map().tempo_at(r->start()); - const Meter& m = session.tempo_map().meter_at(r->start()); - - double q_frames = _q * (m.frames_per_bar(t, session.frame_rate()) / (double)m.beats_per_bar()); - for (Evoral::Sequence<MidiModel::TimeType>::Notes::iterator i = model->notes().begin(); i != model->notes().end(); ++i) { - const double new_time = lrint((*i)->time() / q_frames) * q_frames; - double new_dur = lrint((*i)->length() / q_frames) * q_frames; + const double new_time = lrint((*i)->time() / _q) * _q; + double new_dur = lrint((*i)->length() / _q) * _q; if (new_dur == 0.0) - new_dur = q_frames; + new_dur = _q; (*i)->set_time(new_time); (*i)->set_length(new_dur); diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index 5fd09ef1bb..ab0c290191 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -41,7 +41,6 @@ #include <ardour/midi_ring_buffer.h> #include <ardour/session.h> #include <ardour/smf_source.h> -#include <ardour/tempo.h> #include "i18n.h" @@ -145,13 +144,7 @@ SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t start, nfram size_t scratch_size = 0; // keep track of scratch to minimize reallocs - // FIXME: assumes tempo never changes after start - const Tempo& tempo = _session.tempo_map().tempo_at(_timeline_position); - const double frames_per_beat = tempo.frames_per_beat( - _session.engine().frame_rate(), - _session.tempo_map().meter_at(_timeline_position)); - - const uint64_t start_ticks = (uint64_t)((start / frames_per_beat) * ppqn()); + const uint64_t start_ticks = (uint64_t)(_converter.from(start) * ppqn()); if (_last_read_end == 0 || start != _last_read_end) { cerr << "SMFSource::read_unlocked seeking to " << start << endl; @@ -183,8 +176,7 @@ SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t start, nfram ev_type = EventTypeMap::instance().midi_event_type(ev_buffer[0]); assert(time >= start_ticks); - const nframes_t ev_frame_time = (nframes_t)( - ((time / (double)ppqn()) * frames_per_beat)) + stamp_offset; + const nframes_t ev_frame_time = _converter.to(time / (double)ppqn()) + stamp_offset; if (ev_frame_time < start + dur) { dst.write(ev_frame_time - negative_stamp_offset, ev_type, ev_size, ev_buffer); @@ -323,24 +315,19 @@ SMFSource::append_event_unlocked_frames(const Evoral::Event<nframes_t>& ev) return; } - // FIXME: assumes tempo never changes after start - const Tempo& tempo = _session.tempo_map().tempo_at(_timeline_position); - const double frames_per_beat = tempo.frames_per_beat( - _session.engine().frame_rate(), - _session.tempo_map().meter_at(_timeline_position)); - - uint32_t delta_time = (uint32_t)((ev.time() - _last_ev_time_frames) - / frames_per_beat * (double)ppqn()); + const nframes_t delta_time_frames = ev.time() - _last_ev_time_frames; + const double delta_time_beats = _converter.from(delta_time_frames); + const uint32_t delta_time_ticks = (uint32_t)(lrint(delta_time_beats * (double)ppqn())); - Evoral::SMF::append_event_delta(delta_time, ev.size(), ev.buffer()); + Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer()); _last_ev_time_frames = ev.time(); _write_data_count += ev.size(); if (_model) { - double beat_time = ev.time() / frames_per_beat; + const double ev_time_beats = _converter.from(ev.time()); const Evoral::Event<double> beat_ev( - ev.event_type(), beat_time, ev.size(), (uint8_t*)ev.buffer()); + ev.event_type(), ev_time_beats, ev.size(), (uint8_t*)ev.buffer()); _model->append(beat_ev); } } diff --git a/libs/evoral/evoral/TimeConverter.hpp b/libs/evoral/evoral/TimeConverter.hpp new file mode 100644 index 0000000000..3f434d9dd7 --- /dev/null +++ b/libs/evoral/evoral/TimeConverter.hpp @@ -0,0 +1,43 @@ +/* This file is part of Evoral. + * Copyright (C) 2009 Dave Robillard <http://drobilla.net> + * Copyright (C) 2009 Paul Davis + * + * Evoral 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. + * + * Evoral 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 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., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef EVORAL_TIME_CONVERTER_HPP +#define EVORAL_TIME_CONVERTER_HPP + +namespace Evoral { + +/** A bidirectional converter between two different time units. + * + * Think of the conversion method names as if they are written in-between + * the two template parameters (i.e. "A <name> B"). + */ +template<typename A, typename B> +class TimeConverter { +public: + virtual ~TimeConverter() {} + + /** Convert A time to B time (A to B) */ + virtual B to(A a) const = 0; + + /** Convert B time to A time (A from B) */ + virtual A from(B b) const = 0; +}; + +} // namespace Evoral + +#endif // EVORAL_TIME_CONVERTER_HPP |