mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-04 12:45:45 +01:00
Fix metronome when looping
This commit is contained in:
parent
08fdb98262
commit
804f9c9bde
1 changed files with 91 additions and 33 deletions
|
|
@ -58,8 +58,6 @@ Session::add_click (samplepos_t pos, bool emphasis)
|
|||
void
|
||||
Session::click (samplepos_t cycle_start, samplecnt_t nframes)
|
||||
{
|
||||
vector<TempoMap::BBTPoint> points; // TODO use mempool allocator
|
||||
|
||||
if (_click_io == 0) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -87,32 +85,64 @@ Session::click (samplepos_t cycle_start, samplecnt_t nframes)
|
|||
|
||||
/* range to check for clicks */
|
||||
samplepos_t start = cycle_start + offset;
|
||||
const samplepos_t end = start + nframes;
|
||||
/* correct start, potentially */
|
||||
start = max (start, (samplepos_t) 0);
|
||||
|
||||
if (end > start) {
|
||||
_tempo_map->get_grid (points, start, end);
|
||||
}
|
||||
samplecnt_t remain = nframes;
|
||||
|
||||
if (distance (points.begin(), points.end()) == 0) {
|
||||
goto run_clicks;
|
||||
}
|
||||
while (remain > 0) {
|
||||
samplecnt_t move = remain;
|
||||
|
||||
for (vector<TempoMap::BBTPoint>::iterator i = points.begin(); i != points.end(); ++i) {
|
||||
switch ((*i).beat) {
|
||||
case 1:
|
||||
add_click ((*i).sample, true);
|
||||
break;
|
||||
default:
|
||||
if (click_emphasis_data == 0 || (Config->get_use_click_emphasis () == false) || (click_emphasis_data && (*i).beat != 1)) { // XXX why is this check needed ?? (*i).beat !=1 must be true here
|
||||
add_click ((*i).sample, false);
|
||||
Location* loop_location = locations()->auto_loop_location ();
|
||||
if (loop_location) {
|
||||
const samplepos_t loop_start = loop_location->start ();
|
||||
const samplepos_t loop_end = loop_location->end ();
|
||||
if (start >= loop_end) {
|
||||
samplecnt_t off = (start - loop_end) % (loop_end - loop_start);
|
||||
start = loop_start + off;
|
||||
move = std::min (remain, loop_end - start);
|
||||
} else if (start + move >= loop_end) {
|
||||
move = std::min (remain, loop_end - start);
|
||||
}
|
||||
if (move == 0) {
|
||||
start = loop_start;
|
||||
const samplecnt_t looplen = loop_end - loop_start;
|
||||
move = std::min (remain, looplen);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const samplepos_t end = start + move;
|
||||
|
||||
vector<TempoMap::BBTPoint> points; // TODO use mempool allocator
|
||||
_tempo_map->get_grid (points, start, end);
|
||||
|
||||
if (distance (points.begin(), points.end()) == 0) {
|
||||
start += move;
|
||||
remain -= move;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (vector<TempoMap::BBTPoint>::iterator i = points.begin(); i != points.end(); ++i) {
|
||||
if ((*i).sample < start || (*i).sample >= end) {
|
||||
// FIXME: TempoMap::get_grid() returns duplicates and out of range points
|
||||
continue;
|
||||
}
|
||||
switch ((*i).beat) {
|
||||
case 1:
|
||||
add_click ((*i).sample, true);
|
||||
break;
|
||||
default:
|
||||
if (click_emphasis_data == 0 || (Config->get_use_click_emphasis () == false) || (click_emphasis_data && (*i).beat != 1)) { // XXX why is this check needed ?? (*i).beat !=1 must be true here
|
||||
add_click ((*i).sample, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
start += move;
|
||||
remain -= move;
|
||||
}
|
||||
|
||||
run_clicks:
|
||||
clickm.release ();
|
||||
run_click (cycle_start, nframes);
|
||||
}
|
||||
|
|
@ -135,31 +165,59 @@ Session::run_click (samplepos_t start, samplepos_t nframes)
|
|||
buf = bufs.get_audio(0).data();
|
||||
memset (buf, 0, sizeof (Sample) * nframes);
|
||||
|
||||
/* given a large output latency, `start' can be offset by by > 1 cycle.
|
||||
* and needs to be mapped back into the loop-range */
|
||||
Location* loop_location = locations()->auto_loop_location ();
|
||||
bool crossloop = false;
|
||||
samplecnt_t span = nframes;
|
||||
if (loop_location) {
|
||||
const samplepos_t loop_start = loop_location->start ();
|
||||
const samplepos_t loop_end = loop_location->end ();
|
||||
if (start >= loop_end) {
|
||||
samplecnt_t off = (start - loop_end) % (loop_end - loop_start);
|
||||
start = loop_start + off;
|
||||
span = std::min (nframes, loop_end - start);
|
||||
} else if (start + nframes >= loop_end) {
|
||||
crossloop = true;
|
||||
span = std::min (nframes, loop_end - start);
|
||||
}
|
||||
}
|
||||
|
||||
for (list<Click*>::iterator i = clicks.begin(); i != clicks.end(); ) {
|
||||
|
||||
samplecnt_t copy;
|
||||
Click *clk = *i;
|
||||
|
||||
if (loop_location) {
|
||||
const samplepos_t loop_start = loop_location->start ();
|
||||
const samplepos_t loop_end = loop_location->end ();
|
||||
/* remove any clicks that are outside loop location, and not currently playing */
|
||||
if ((clk->start < loop_start || clk->start >= loop_end) && clk->offset == 0) {
|
||||
delete clk;
|
||||
i = clicks.erase (i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
samplecnt_t internal_offset;
|
||||
Click *clk;
|
||||
|
||||
clk = *i;
|
||||
|
||||
if (clk->start < start) {
|
||||
if (clk->start <= start || clk->offset > 0) {
|
||||
internal_offset = 0;
|
||||
} else {
|
||||
} else if (clk->start < start + span) {
|
||||
/* queue click at offset in current cycle */
|
||||
internal_offset = clk->start - start;
|
||||
} else if (crossloop) {
|
||||
/* When loop wraps around in current cycle, take
|
||||
* clicks at loop-start into account */
|
||||
const samplepos_t loop_start = loop_location->start ();
|
||||
internal_offset = clk->start - loop_start + span;
|
||||
}
|
||||
|
||||
if (nframes < internal_offset) {
|
||||
/* we've just located or something..
|
||||
effectively going backwards.
|
||||
lets get the flock out of here */
|
||||
break;
|
||||
if (internal_offset >= nframes) {
|
||||
break;
|
||||
}
|
||||
|
||||
copy = min (clk->duration - clk->offset, nframes - internal_offset);
|
||||
|
||||
samplecnt_t copy = min (clk->duration - clk->offset, nframes - internal_offset);
|
||||
memcpy (buf + internal_offset, &clk->data[clk->offset], copy * sizeof (Sample));
|
||||
|
||||
clk->offset += copy;
|
||||
|
||||
if (clk->offset >= clk->duration) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue