readerSource->setLooping(false) causes audio play back to stop

If I set readerSource->setLooping(false) and the audio file has already looped the audio play back stops. Is this a bug or am I misunderstanding how setLooping works? If it is a bug is there a workaround?

There was discussion about this around seven years ago but I don’t see anything more recent.
I believe I’m using the latest version of JUCE.

Thanks,
Stephen

It’s a bug. The problem is that the value of nextPlayPos gets higher and higher on each play-repeat, whereas it should reset to zero when starting again.

The getNextReadPosition() and getNextAudioBlock() methods get away with it because of their use of the modulo operator (the % symbol). But as soon as looping is switched off, the modulo operator is no longer applied, and you end up with a crazy high value for nextPlayPos.

A few ways to go, imo:-

  • fix in AudioFormatReaderSource and submit a PR
  • raise an issue on GitHub and ask the core team to fix
  • write your own version of AudioFormatReaderSource with the fix, and use that instead.

I wrote my own version of AudioFormatReaderSource in order to better control looping between user-set start/end loop points, and in doing so found and fixed this bug in my version. The code looks like this:-

juce::int64 RomplerAudioReaderSource::getNextReadPosition() const
{
#if false
    // original
    return looping ? nextPlayPos % reader->lengthInSamples
        : nextPlayPos;
#else
    // new code, to stop 'nextPlayPos' advancing higher and higher forever
    if (!looping)
    {
        return nextPlayPos;
    }
    else
    {
        if (nextPlayPos < reader->lengthInSamples)
        {
            return nextPlayPos;
        }

        nextPlayPos = nextPlayPos % reader->lengthInSamples;
        return nextPlayPos;
    }
#endif
}

Two extra things to do:-

  1. Mark field nextPlayPos as mutable in the header file, otherwise getNextReadPosition() won’t be able to update it.
  2. Change getNextAudioBlock() to set readFrom by calling the now-correct getNextReadPosition() method, instead of repeating the computation.

--

I’m not saying that the above is the best solution. But it’s a hacky fix that works in my private version of AudioFormatReaderSource. Perhaps a better way is to wrap-around nextPlayPos just after incrementing it.