- /* We now have:
-
- meter -> the Meter for "lower"
- tempo -> the Tempo for "lower"
- i -> for first new metric after "lower", possibly metrics->end()
-
- Now start generating points.
- */
-
- divisions_per_bar = meter->divisions_per_bar ();
- frames_per_bar = meter->frames_per_bar (*tempo, _frame_rate);
- beat_frames = meter->frames_per_division (*tempo,_frame_rate);
-
- if (meter->frame() > tempo->frame()) {
- bar = meter->start().bars;
- beat = meter->start().beats;
- current = meter->frame();
- } else {
- bar = tempo->start().bars;
- beat = tempo->start().beats;
- current = tempo->frame();
- }
-
- /* initialize current to point to the bar/beat just prior to the
- lower frame bound passed in. assumes that current is initialized
- above to be on a beat.
- */
-
- delta_bars = (lower-current) / frames_per_bar;
- delta_beats = modf(delta_bars, &dummy) * divisions_per_bar;
- current += (floor(delta_bars) * frames_per_bar) + (floor(delta_beats) * beat_frames);
-
- // adjust bars and beats too
- bar += (uint32_t) (floor(delta_bars));
- beat += (uint32_t) (floor(delta_beats));
-
- points = new BBTPointList;
-
- do {
-
- if (i == metrics->end()) {
- limit = upper;
- // cerr << "== limit set to end of request @ " << limit << endl;
- } else {
- // cerr << "== limit set to next metric @ " << (*i)->frame() << endl;
- limit = (*i)->frame();
- }
-
- limit = min (limit, upper);
-
- while (current < limit) {
-
- /* if we're at the start of a bar, add bar point */
-
- if (beat == 1) {
- if (current >= lower) {
- // cerr << "Add Bar at " << bar << "|1" << " @ " << current << endl;
- points->push_back (BBTPoint (*meter, *tempo,(framepos_t)rint(current), Bar, bar, 1));
-
- }
- }
-
- /* add some beats if we can */
-
- beat_frame = current;
-
- while (beat <= ceil(divisions_per_bar) && beat_frame < limit) {
- if (beat_frame >= lower) {
- // cerr << "Add Beat at " << bar << '|' << beat << " @ " << beat_frame << endl;
- points->push_back (BBTPoint (*meter, *tempo, (framepos_t) rint(beat_frame), Beat, bar, beat));
- }
- beat_frame += beat_frames;
- current+= beat_frames;
-
- beat++;
- }
-
- // cerr << "out of beats, @ end ? " << (i == metrics->end()) << " out of bpb ? "
- // << (beat > ceil(divisions_per_bar))
- // << " beat frame @ " << beat_frame << " vs. " << limit
- // << endl;
-
- if (beat > ceil(divisions_per_bar) || i != metrics->end()) {
-
- /* we walked an entire bar. its
- important to move `current' forward
- by the actual frames_per_bar, not move it to
- an integral beat_frame, so that metrics with
- non-integral beats-per-bar have
- their bar positions set
- correctly. consider a metric with
- 9-1/2 beats-per-bar. the bar we
- just filled had 10 beat marks,
- but the bar end is 1/2 beat before
- the last beat mark.
- And it is also possible that a tempo
- change occured in the middle of a bar,
- so we subtract the possible extra fraction from the current
- */
-
- if (beat > ceil (divisions_per_bar)) {
- /* next bar goes where the numbers suggest */
- current -= beat_frames * (ceil(divisions_per_bar)-divisions_per_bar);
- // cerr << "++ next bar from numbers\n";
- } else {
- /* next bar goes where the next metric is */
- current = limit;
- // cerr << "++ next bar at next metric\n";
- }
- bar++;
- beat = 1;
- }
-
- }
-
- /* if we're done, then we're done */
-
- if (current >= upper) {
- break;
- }
-
- /* i is an iterator that refers to the next metric (or none).
- if there is a next metric, move to it, and continue.
- */
-
- if (i != metrics->end()) {
-
- if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
- tempo = t;
- } else if ((m = dynamic_cast<const MeterSection*>(*i)) != 0) {
- meter = m;
- /* new MeterSection, beat always returns to 1 */
- beat = 1;
- }
-
- current = (*i)->frame ();
- // cerr << "loop around with current @ " << current << endl;
-
- divisions_per_bar = meter->divisions_per_bar ();
- frames_per_bar = meter->frames_per_bar (*tempo, _frame_rate);
- beat_frames = meter->frames_per_division (*tempo, _frame_rate);
-
- ++i;
- }
-
- } while (1);
-
- return points;