summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2008-01-19 21:13:45 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2008-01-19 21:13:45 +0000
commit89d564186d0b41469cf56ca3f400f98d3ddcfce8 (patch)
tree3824c6fb6d96a26a00346d848309ff982e852297
parent95a24f9707c342ea1764eb8d1de0a9c73eda84df (diff)
fixes and bindings for region gain control; set-tempo-from-region implementation : please test and look for tempo/meter related bugs
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2950 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/ardour.bindings.in14
-rw-r--r--gtk2_ardour/ardour.menus1
-rw-r--r--gtk2_ardour/editor.h2
-rw-r--r--gtk2_ardour/editor_actions.cc3
-rw-r--r--gtk2_ardour/editor_ops.cc65
-rw-r--r--libs/ardour/ardour/tempo.h20
-rw-r--r--libs/ardour/tempo.cc289
7 files changed, 273 insertions, 121 deletions
diff --git a/gtk2_ardour/ardour.bindings.in b/gtk2_ardour/ardour.bindings.in
index 1efdb1cdd4..9dbbd8deff 100644
--- a/gtk2_ardour/ardour.bindings.in
+++ b/gtk2_ardour/ardour.bindings.in
@@ -38,6 +38,10 @@
(gtk_accel_path "<Actions>/Editor/set-punch-from-edit-range" "bracketleft")
(gtk_accel_path "<Actions>/Editor/set-punch-from-region" "<%SECONDARY%>bracketleft")
+(gtk_accel_path "<Actions>/Editor/boost-region-gain" "asciicircum")
+(gtk_accel_path "<Actions>/Editor/cut-region-gain" "ampersand")
+(gtk_accel_path "<Actions>/Editor/set-tempo-from-region" "asterisk")
+
;; letters
;; TOP ROW
@@ -50,6 +54,7 @@
(gtk_accel_path "<Actions>/Editor/select-all-before-edit-cursor" "<%PRIMARY%>e")
(gtk_accel_path "<Actions>/Editor/show-editor-mixer" "<%TERTIARY%>e")
(gtk_accel_path "<Actions>/Common/goto-editor" "<%WINDOW%>e")
+(gtk_accel_path "<Actions>/Editor/select-all-after-edit-cursor" "<%TERTIARY%><%PRIMARY%>e")
(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-range" "r")
(gtk_accel_path "<Actions>/Editor/redo" "<%PRIMARY%>r")
(gtk_accel_path "<Actions>/Transport/Record" "<%TERTIARY%>r")
@@ -62,22 +67,19 @@
(gtk_accel_path "<Actions>/Common/ToggleOptionsEditor" "<%WINDOW%>o")
(gtk_accel_path "<Actions>/Editor/set-playhead" "p")
(gtk_accel_path "<Actions>/Editor/select-all-before-playhead" "<%PRIMARY%>p")
+(gtk_accel_path "<Actions>/Editor/select-all-after-playhead" "<%TERTIARY%><%PRIMARY%>p")
;; MIDDLE ROW
(gtk_accel_path "<Actions>/Editor/align-regions-sync-relative" "a")
-(gtk_accel_path "<Actions>/Editor/align-regions-start-relative" "<%PRIMARY%>a")
+(gtk_accel_path "<Actions>/Editor/select-all" "<%PRIMARY%>a")
(gtk_accel_path "<Actions>/Editor/align-regions-end" "<%SECONDARY%>a")
(gtk_accel_path "<Actions>/Editor/align-regions-sync" "<%TERTIARY%>a")
+(gtk_accel_path "<Actions>/Editor/align-regions-start-relative" "<%LEVEL4%>a")
(gtk_accel_path "<Actions>/Editor/split-region" "s")
(gtk_accel_path "<Actions>/Common/Save" "<%PRIMARY%>s")
(gtk_accel_path "<Actions>/Editor/duplicate-region" "d")
(gtk_accel_path "<Actions>/Editor/select-all-in-punch-range" "<%PRIMARY%>d")
-
-(gtk_accel_path "<Actions>/Editor/select-all" "<%PRIMARY%>a")
-(gtk_accel_path "<Actions>/Editor/select-all-after-playhead" "<%TERTIARY%><%PRIMARY%>p")
-(gtk_accel_path "<Actions>/Editor/select-all-after-edit-cursor" "<%TERTIARY%><%PRIMARY%>e")
-
(gtk_accel_path "<Actions>/Editor/toggle-follow-playhead" "f")
(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-gain" "g")
(gtk_accel_path "<Actions>/Editor/play-selected-regions" "h")
diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus
index 73768f3cf4..2237a30ea0 100644
--- a/gtk2_ardour/ardour.menus
+++ b/gtk2_ardour/ardour.menus
@@ -194,6 +194,7 @@
<menuitem action='trim-region-to-punch'/>
<separator/>
<menuitem action='pitch-shift-region'/>
+ <menuitem action='set-tempo-from-region'/>
</menu>
<menu name='View' action = 'View'>
<menu name='ZoomFocus' action='ZoomFocus'>
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index ac67f9015f..ec7554bf3a 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -982,6 +982,8 @@ class Editor : public PublicEditor
void denormalize_region ();
void adjust_region_scale_amplitude (bool up);
+ void use_region_as_bar ();
+
void audition_region_from_region_list ();
void hide_region_from_region_list ();
void remove_region_from_region_list ();
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
index ce33a0177e..0b46253efb 100644
--- a/gtk2_ardour/editor_actions.cc
+++ b/gtk2_ardour/editor_actions.cc
@@ -359,6 +359,9 @@ Editor::register_actions ()
act = ActionManager::register_action (editor_actions, "cut-region-gain", _("Cut Region Gain"), bind (mem_fun(*this, &Editor::adjust_region_scale_amplitude), false));
ActionManager::session_sensitive_actions.push_back (act);
+ act = ActionManager::register_action (editor_actions, "set-tempo-from-region", _("Set Tempo from Region=Bar"), mem_fun(*this, &Editor::use_region_as_bar));
+ ActionManager::session_sensitive_actions.push_back (act);
+
act = ActionManager::register_action (editor_actions, "crop", _("Crop"), mem_fun(*this, &Editor::crop_region_to_selection));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "insert-chunk", _("Insert Chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f));
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 51a6d294cd..11917851f7 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -4119,7 +4119,7 @@ Editor::adjust_region_scale_amplitude (bool up)
return;
}
- ExclusiveRegionSelection (*this, entered_regionview);
+ ExclusiveRegionSelection esr (*this, entered_regionview);
if (selection->regions.empty()) {
return;
@@ -4135,10 +4135,6 @@ Editor::adjust_region_scale_amplitude (bool up)
double fraction = gain_to_slider_position (arv->audio_region()->scale_amplitude ());
- cerr << "slider pos for " << arv->audio_region()->scale_amplitude ()
- << " = " << fraction
- << endl;
-
if (up) {
fraction += 0.05;
fraction = min (fraction, 1.0);
@@ -4151,16 +4147,14 @@ Editor::adjust_region_scale_amplitude (bool up)
continue;
}
- if (up && fraction >= 1.0) {
- continue;
- }
-
fraction = slider_position_to_gain (fraction);
fraction = coefficient_to_dB (fraction);
fraction = dB_to_coefficient (fraction);
-
- cerr << "set scale amp for " << arv->audio_region()->name() << " to " << fraction << endl;
+ if (up && fraction >= 2.0) {
+ continue;
+ }
+
arv->audio_region()->set_scale_amplitude (fraction);
session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
}
@@ -4953,3 +4947,52 @@ Editor::pitch_shift_regions ()
pitch_shift (selection->regions, 1.2);
}
+void
+Editor::use_region_as_bar ()
+{
+ if (!session) {
+ return;
+ }
+
+ ExclusiveRegionSelection esr (*this, entered_regionview);
+
+ if (selection->regions.empty()) {
+ return;
+ }
+
+ RegionView* rv = selection->regions.front();
+
+ const Meter& m (session->tempo_map().meter_at (rv->region()->position()));
+
+ /* region length = 1 bar */
+
+ /* 1 bar = how many beats per bar */
+
+ double beats_per_bar = m.beats_per_bar();
+
+ /* now we want frames per beat.
+ we have frames per bar, and beats per bar, so ...
+ */
+
+ double frames_per_beat = rv->region()->length() / beats_per_bar;
+
+ /* beats per minute = */
+
+ double beats_per_minute = (session->frame_rate() * 60.0) / frames_per_beat;
+
+ const TempoSection& t (session->tempo_map().tempo_section_at (rv->region()->position()));
+
+ begin_reversible_command (_("set tempo from region"));
+ XMLNode& before (session->tempo_map().get_state());
+
+ if (t.frame() == rv->region()->position()) {
+ session->tempo_map().change_existing_tempo_at (rv->region()->position(), beats_per_minute, t.note_type());
+ } else {
+ session->tempo_map().add_tempo (Tempo (beats_per_minute, t.note_type()), rv->region()->position());
+ }
+
+ XMLNode& after (session->tempo_map().get_state());
+
+ session->add_command (new MementoCommand<TempoMap>(session->tempo_map(), &before, &after));
+ commit_reversible_command ();
+}
diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h
index fcd42734b0..fa1d882ab3 100644
--- a/libs/ardour/ardour/tempo.h
+++ b/libs/ardour/ardour/tempo.h
@@ -109,6 +109,9 @@ class MetricSection {
public:
MetricSection (const BBT_Time& start)
: _start (start), _frame (0), _movable (true) {}
+ MetricSection (nframes_t start)
+ : _frame (start), _movable (true) {}
+
virtual ~MetricSection() {}
const BBT_Time& start() const { return _start; }
@@ -142,6 +145,8 @@ class MeterSection : public MetricSection, public Meter {
public:
MeterSection (const BBT_Time& start, double bpb, double note_type)
: MetricSection (start), Meter (bpb, note_type) {}
+ MeterSection (nframes_t start, double bpb, double note_type)
+ : MetricSection (start), Meter (bpb, note_type) {}
MeterSection (const XMLNode&);
static const string xml_state_node_name;
@@ -153,6 +158,8 @@ class TempoSection : public MetricSection, public Tempo {
public:
TempoSection (const BBT_Time& start, double qpm, double note_type)
: MetricSection (start), Tempo (qpm, note_type) {}
+ TempoSection (nframes_t start, double qpm, double note_type)
+ : MetricSection (start), Tempo (qpm, note_type) {}
TempoSection (const XMLNode&);
static const string xml_state_node_name;
@@ -165,7 +172,6 @@ typedef list<MetricSection*> Metrics;
class TempoMap : public PBD::StatefulDestructible
{
public:
-
TempoMap (nframes_t frame_rate);
~TempoMap();
@@ -207,9 +213,14 @@ class TempoMap : public PBD::StatefulDestructible
const Tempo& tempo_at (nframes_t);
const Meter& meter_at (nframes_t);
+ const TempoSection& tempo_section_at (nframes_t);
+
void add_tempo(const Tempo&, BBT_Time where);
void add_meter(const Meter&, BBT_Time where);
+ void add_tempo(const Tempo&, nframes_t where);
+ void add_meter(const Meter&, nframes_t where);
+
void move_tempo (TempoSection&, const BBT_Time& to);
void move_meter (MeterSection&, const BBT_Time& to);
@@ -267,6 +278,8 @@ class TempoMap : public PBD::StatefulDestructible
Metric metric_at (nframes_t) const;
void bbt_time_with_metric (nframes_t, BBT_Time&, const Metric&) const;
+ void change_existing_tempo_at (nframes_t, double bpm, double note_type);
+
sigc::signal<void,ARDOUR::Change> StateChanged;
private:
@@ -280,8 +293,7 @@ class TempoMap : public PBD::StatefulDestructible
BBT_Time last_bbt;
mutable Glib::RWLock lock;
- void timestamp_metrics ();
-
+ void timestamp_metrics (bool use_bbt);
nframes_t round_to_type (nframes_t fr, int dir, BBTPointType);
@@ -298,7 +310,7 @@ class TempoMap : public PBD::StatefulDestructible
nframes_t count_frames_between_metrics (const Meter&, const Tempo&, const BBT_Time&, const BBT_Time&) const;
int move_metric_section (MetricSection&, const BBT_Time& to);
- void do_insert (MetricSection* section);
+ void do_insert (MetricSection* section, bool with_bbt);
};
}; /* namespace ARDOUR */
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
index 780f5c6a5d..6e74c49859 100644
--- a/libs/ardour/tempo.cc
+++ b/libs/ardour/tempo.cc
@@ -268,7 +268,7 @@ TempoMap::move_metric_section (MetricSection& section, const BBT_Time& when)
section.set_start (corrected);
metrics->sort (cmp);
- timestamp_metrics ();
+ timestamp_metrics (true);
return 0;
}
@@ -345,16 +345,22 @@ TempoMap::remove_meter (const MeterSection& tempo)
}
void
-TempoMap::do_insert (MetricSection* section)
+TempoMap::do_insert (MetricSection* section, bool with_bbt)
{
Metrics::iterator i;
for (i = metrics->begin(); i != metrics->end(); ++i) {
- if ((*i)->start() < section->start()) {
- continue;
+ if (with_bbt) {
+ if ((*i)->start() < section->start()) {
+ continue;
+ }
+ } else {
+ if ((*i)->frame() < section->frame()) {
+ continue;
+ }
}
-
+
metrics->insert (i, section);
break;
}
@@ -363,7 +369,7 @@ TempoMap::do_insert (MetricSection* section)
metrics->insert (metrics->end(), section);
}
- timestamp_metrics ();
+ timestamp_metrics (with_bbt);
}
void
@@ -376,7 +382,18 @@ TempoMap::add_tempo (const Tempo& tempo, BBT_Time where)
where.ticks = 0;
- do_insert (new TempoSection (where, tempo.beats_per_minute(), tempo.note_type()));
+ do_insert (new TempoSection (where, tempo.beats_per_minute(), tempo.note_type()), true);
+ }
+
+ StateChanged (Change (0));
+}
+
+void
+TempoMap::add_tempo (const Tempo& tempo, nframes_t where)
+{
+ {
+ Glib::RWLock::WriterLock lm (lock);
+ do_insert (new TempoSection (where, tempo.beats_per_minute(), tempo.note_type()), false);
}
StateChanged (Change (0));
@@ -399,7 +416,7 @@ TempoMap::replace_tempo (TempoSection& existing, const Tempo& replacement)
*((Tempo *) ts) = replacement;
replaced = true;
- timestamp_metrics ();
+ timestamp_metrics (true);
break;
}
}
@@ -432,7 +449,18 @@ TempoMap::add_meter (const Meter& meter, BBT_Time where)
where.ticks = 0;
- do_insert (new MeterSection (where, meter.beats_per_bar(), meter.note_divisor()));
+ do_insert (new MeterSection (where, meter.beats_per_bar(), meter.note_divisor()), false);
+ }
+
+ StateChanged (Change (0));
+}
+
+void
+TempoMap::add_meter (const Meter& meter, nframes_t where)
+{
+ {
+ Glib::RWLock::WriterLock lm (lock);
+ do_insert (new MeterSection (where, meter.beats_per_bar(), meter.note_divisor()), true);
}
StateChanged (Change (0));
@@ -454,7 +482,7 @@ TempoMap::replace_meter (MeterSection& existing, const Meter& replacement)
*((Meter*) ms) = replacement;
replaced = true;
- timestamp_metrics ();
+ timestamp_metrics (true);
break;
}
}
@@ -465,6 +493,49 @@ TempoMap::replace_meter (MeterSection& existing, const Meter& replacement)
}
}
+void
+TempoMap::change_existing_tempo_at (nframes_t where, double beats_per_minute, double note_type)
+{
+ Tempo newtempo (beats_per_minute, note_type);
+
+ TempoSection* prev;
+ TempoSection* first;
+ Metrics::iterator i;
+
+ /* find the TempoSection immediately preceding "where"
+ */
+
+ for (first = 0, i = metrics->begin(), prev = 0; i != metrics->end(); ++i) {
+
+ if ((*i)->frame() > where) {
+ break;
+ }
+
+ TempoSection* t;
+
+ if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
+ if (!first) {
+ first = t;
+ }
+ prev = t;
+ }
+ }
+
+ if (!prev) {
+ if (!first) {
+ error << string_compose (_("no tempo sections defined in tempo map - cannot change tempo @ %1"), where) << endmsg;
+ return;
+ }
+
+ prev = first;
+ }
+
+ /* reset */
+
+ *((Tempo*)prev) = newtempo;
+ StateChanged (Change (0));
+}
+
const MeterSection&
TempoMap::first_meter () const
{
@@ -498,43 +569,84 @@ TempoMap::first_tempo () const
}
void
-TempoMap::timestamp_metrics ()
+TempoMap::timestamp_metrics (bool use_bbt)
{
Metrics::iterator i;
const Meter* meter;
const Tempo* tempo;
Meter *m;
Tempo *t;
- nframes_t current;
- nframes_t section_frames;
- BBT_Time start;
- BBT_Time end;
meter = &first_meter ();
tempo = &first_tempo ();
- current = 0;
- for (i = metrics->begin(); i != metrics->end(); ++i) {
-
- end = (*i)->start();
+ if (use_bbt) {
- section_frames = count_frames_between_metrics (*meter, *tempo, start, end);
+ nframes_t current = 0;
+ nframes_t section_frames;
+ BBT_Time start;
+ BBT_Time end;
- current += section_frames;
+ for (i = metrics->begin(); i != metrics->end(); ++i) {
+
+ end = (*i)->start();
+
+ section_frames = count_frames_between_metrics (*meter, *tempo, start, end);
+
+ current += section_frames;
+
+ start = end;
+
+ (*i)->set_frame (current);
+
+ if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
+ tempo = t;
+ } else if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
+ meter = m;
+ } else {
+ fatal << _("programming error: unhandled MetricSection type") << endmsg;
+ /*NOTREACHED*/
+ }
+ }
- start = end;
+ } else {
- (*i)->set_frame (current);
+ bool first = true;
- if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
- tempo = t;
- } else if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
- meter = m;
- } else {
- fatal << _("programming error: unhandled MetricSection type") << endmsg;
- /*NOTREACHED*/
+ for (i = metrics->begin(); i != metrics->end(); ++i) {
+
+ BBT_Time bbt;
+
+ bbt_time_with_metric ((*i)->frame(), bbt, Metric (*meter, *tempo));
+
+ // cerr << "timestamp @ " << (*i)->frame() << " with " << bbt.bars << "|" << bbt.beats << "|" << bbt.ticks << " => ";
+
+ if (first) {
+ first = false;
+ } else {
+ if (bbt.beats != 1 || bbt.ticks != 0) {
+ bbt.bars += 1;
+ bbt.beats = 1;
+ bbt.ticks = 0;
+ }
+ }
+
+ // cerr << bbt.bars << "|" << bbt.beats << "|" << bbt.ticks << endl;
+
+ (*i)->set_start (bbt);
+
+ if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
+ tempo = t;
+ } else if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
+ meter = m;
+ } else {
+ fatal << _("programming error: unhandled MetricSection type") << endmsg;
+ /*NOTREACHED*/
+ }
}
}
+
+ // dump (cerr);
}
TempoMap::Metric
@@ -666,17 +778,15 @@ TempoMap::bbt_time_with_metric (nframes_t frame, BBT_Time& bbt, const Metric& me
nframes_t
TempoMap::count_frames_between ( const BBT_Time& start, const BBT_Time& end) const
{
-
- /* for this to work with fractional measure types, start and end have to "legal" BBT types,
- that means that the beats and ticks should be inside a bar
+ /* for this to work with fractional measure types, start and end have to be "legal" BBT types,
+ that means that the beats and ticks should be inside a bar
*/
-
nframes_t frames = 0;
nframes_t start_frame = 0;
nframes_t end_frame = 0;
- Metric m = metric_at(start);
+ Metric m = metric_at (start);
uint32_t bar_offset = start.bars - m.start().bars;
@@ -939,67 +1049,6 @@ TempoMap::round_to_beat_subdivision (nframes_t fr, int sub_num)
}
return frame_time (the_beat);
-
-
-
- /*****************************
- XXX just keeping this for reference
-
- TempoMap::BBTPointList::iterator i;
- TempoMap::BBTPointList *more_zoomed_bbt_points;
- nframes_t frame_one_beats_worth;
- nframes_t pos = 0;
- nframes_t next_pos = 0 ;
- double tempo = 1;
- double frames_one_subdivisions_worth;
- bool fr_has_changed = false;
-
- int n;
-
- frame_one_beats_worth = (nframes_t) ::floor ((double) _frame_rate * 60 / 20 ); //one beat @ 20 bpm
- {
- Glib::RWLock::ReaderLock lm (lock);
- more_zoomed_bbt_points = get_points((fr >= frame_one_beats_worth) ?
- fr - frame_one_beats_worth : 0, fr+frame_one_beats_worth );
- }
- if (more_zoomed_bbt_points == 0 || more_zoomed_bbt_points->empty()) {
- return fr;
- }
-
- for (i = more_zoomed_bbt_points->begin(); i != more_zoomed_bbt_points->end(); i++) {
- if ((*i).frame <= fr) {
- pos = (*i).frame;
- tempo = (*i).tempo->beats_per_minute();
-
- } else {
- i++;
- next_pos = (*i).frame;
- break;
- }
- }
- frames_one_subdivisions_worth = ((double) _frame_rate * 60 / (sub_num * tempo));
-
- for (n = sub_num; n > 0; n--) {
- if (fr >= (pos + ((n - 0.5) * frames_one_subdivisions_worth))) {
- fr = (nframes_t) round(pos + (n * frames_one_subdivisions_worth));
- if (fr > next_pos) {
- fr = next_pos; //take care of fractional beats that don't match the subdivision asked
- }
- fr_has_changed = true;
- break;
- }
- }
-
- if (!fr_has_changed) {
- fr = pos;
- }
-
- delete more_zoomed_bbt_points;
- return fr ;
-
- ******************************/
-
-
}
nframes_t
@@ -1051,6 +1100,12 @@ TempoMap::round_to_type (nframes_t frame, int dir, BBTPointType type)
}
+ /*
+ cerr << "for " << frame << " round to " << bbt << " using "
+ << metric.start()
+ << endl;
+ */
+
return metric.frame() + count_frames_between (metric.start(), bbt);
}
@@ -1148,6 +1203,7 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
if (beat == 1) {
if (current >= lower) {
+ // cerr << "Add Bar at " << bar << "|1" << " @ " << current << endl;
points->push_back (BBTPoint (*meter, *tempo,(nframes_t)rint(current), Bar, bar, 1));
}
@@ -1159,6 +1215,7 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
while (beat <= ceil( beats_per_bar) && beat_frame < limit) {
if (beat_frame >= lower) {
+ // cerr << "Add Beat at " << bar << '|' << beat << " @ " << beat_frame << endl;
points->push_back (BBTPoint (*meter, *tempo, (nframes_t) rint(beat_frame), Beat, bar, beat));
}
beat_frame += beat_frames;
@@ -1167,7 +1224,7 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
beat++;
}
- if (beat > ceil(beats_per_bar) ) {
+ if (beat > ceil(beats_per_bar) || i != metrics->end()) {
/* we walked an entire bar. its
important to move `current' forward
@@ -1185,10 +1242,15 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
so we subtract the possible extra fraction from the current
*/
- current -= beat_frames * (ceil(beats_per_bar)-beats_per_bar);
+ if (beat > ceil (beats_per_bar)) {
+ /* next bar goes where the numbers suggest */
+ current -= beat_frames * (ceil(beats_per_bar)-beats_per_bar);
+ } else {
+ /* next bar goes where the next metric is */
+ current = limit;
+ }
bar++;
beat = 1;
-
}
}
@@ -1225,6 +1287,33 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
return points;
}
+const TempoSection&
+TempoMap::tempo_section_at (nframes_t frame)
+{
+ Glib::RWLock::ReaderLock lm (lock);
+ Metrics::iterator i;
+ TempoSection* prev = 0;
+
+ for (i = metrics->begin(); i != metrics->end(); ++i) {
+ TempoSection* t;
+
+ if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+
+ if ((*i)->frame() > frame) {
+ break;
+ }
+
+ prev = t;
+ }
+ }
+
+ if (prev == 0) {
+ fatal << endmsg;
+ }
+
+ return *prev;
+}
+
const Tempo&
TempoMap::tempo_at (nframes_t frame)
{
@@ -1303,7 +1392,7 @@ TempoMap::set_state (const XMLNode& node)
MetricSectionSorter cmp;
metrics->sort (cmp);
- timestamp_metrics ();
+ timestamp_metrics (true);
}
}