Browse Source

Timeline: Fix rare segfault which occurred when region loop point is just beyond the end of a region and at the beginning of a buffer.

tags/non-daw-v1.3.0
Jonathan Moore Liles 3 years ago
parent
commit
b13d2da674
1 changed files with 36 additions and 12 deletions
  1. +36
    -12
      timeline/src/Engine/Audio_Region.C

+ 36
- 12
timeline/src/Engine/Audio_Region.C View File

@@ -118,10 +118,12 @@ Audio_Region::read ( sample_t *buf, bool buf_is_empty, nframes_t pos, nframes_t

const Range r = _range;

/* ASSERT( r.legnth > 0, "Region has zero length!" ); */

const nframes_t rS = r.start;
const nframes_t rE = r.start + r.length;
const nframes_t rE = r.start + r.length; /* one more than the last frame of the region! */
const nframes_t bS = pos;
const nframes_t bE = pos + nframes;
const nframes_t bE = pos + nframes; /* one more than the last frame of the buffer! */
/* do nothing if region isn't inside buffer */
if ( bS > rE || bE < rS )
@@ -188,20 +190,42 @@ Audio_Region::read ( sample_t *buf, bool buf_is_empty, nframes_t pos, nframes_t
WARNING("Loop size (%lu) is smaller than buffer size (%lu). Behavior undefined.", _loop, nframes );
}
const nframes_t lO = sO % _loop; /* how far we are into the loop */
const nframes_t nthloop = sO / _loop; /* which loop iteration */
const nframes_t seam_L = rS + ( nthloop * _loop ); /* receding seam */
const nframes_t seam_R = rS + ( (nthloop + 1 ) * _loop ); /* upcoming seam */
const nframes_t lO = sO % _loop, /* how far we are into the loop */
nthloop = sO / _loop, /* which loop iteration */
seam_L = rS + ( nthloop * _loop ), /* receding seam */
seam_R = rS + ( ( nthloop + 1 ) * _loop ); /* upcoming seam */
/* read interleaved channels */
if ( seam_R > bS && seam_R < bE )
if (
/* this buffer contains a loop boundary, which lies on neither the first or the last frame, and therefore requires a splice of two reads from separate parts of the region. */
seam_R > bS && seam_R < bE
&&
/* but if the end seam of the loop is also the end seam of the region, we only need one read */
seam_R != rE
&&
/* also, if the seam is within the buffer, but beyond the end of the region (as in last loop iteration), do the simpler read in the else clause */
seam_R <= rE
)
{
/* this buffer covers a loop boundary */

/* this buffer covers a loop boundary */
/* read the first part */
cnt = _clip->read( cbuf + ( _clip->channels() * bO ), -1, r.offset + lO, ( seam_R - bS ) - bO );
cnt = _clip->read(
cbuf + ( _clip->channels() * bO ), /* buf */
-1, /* chan */
r.offset + lO, /* start */
( seam_R - bS ) - bO /* len */
);

/* ASSERT( len > cnt, "Error in region looping calculations" ); */
/* read the second part */
cnt += _clip->read( cbuf + ( _clip->channels() * ( bO + cnt ) ), -1, r.offset + 0, ( len - cnt ) - bO );
cnt += _clip->read(
cbuf + ( _clip->channels() * ( bO + cnt ) ), /* buf */
-1, /* chan */
r.offset + 0, /* start */
( len - cnt ) - bO /* len */
);

/* assert( cnt == len ); */
}


Loading…
Cancel
Save