BufferPlayerNode assertion upon using .start(when)


#1

Hi,

Problem

I am having difficulties playing audio starting at a specific time using BufferPlayerNode and the .start(when) method.

Diagnosis

At runtime, an assertion is triggered in another thread:

Assertion failed: (frameOffset + numFrames <= this->getNumFrames()), function copyOffset, file /Users/callumhoward/codeoncanvas/Cinder.git/include/cinder/audio/Buffer.h, line 155.

The frameOffset variable in the assertion frame appears like it may be uninitialised as it is a very large value: frameOffset size_t 18446744073709442560

Steps to reproduce

I have come up with a simple way to reproduce this problem:
Start with the BufferPlayerApp sample code found here, and change line 82 from

	mBufferPlayerNode->start();

to add a time to start from: 0.0.

	mBufferPlayerNode->start(0.0);

expected behaviour should be identical to before the change.

I have searched the forums and github issues, but nothing seems to come up. I must be misunderstanding how it should be used.

I am on release 0.9.1 on macOS 10.12.6 using Xcode 8.3.3


VoiceSamplePlayer WAV Assertion fail
#2

Looking at the cinder source, the when appears not to be a time offset into the BufferNode, but a delay after which to start playing. I agree that calling start(0.0) should probably fall back to just calling start() (or maybe be renamed to startIn (float secondsFromNow)), but this explains why you’re seeing what you’re seeing.

@rich.e is the man you want to speak to, though.


#3

Thanks for clearing that up. I’ll use start() and then call seekToTime().


#4

Yes the double argument to start() and enable() methods represent an offset into the audio graph’s notion of time, it has nothing to do with the sample being played. This was an idea borrowed from the Web Audio api, although I don’t think it is an optional argument there (can’t remember). We could perhaps rename it to startAt( when ), but I sort of like having less methods and in this case I think the in line docs should get you on the right track (and please let me know if there is a way to word this better). I will look into making sure that assertion doesn’t fire, though, I imagine that if you specify any time that is in the ‘past’ (for the audio thread), then it will just start / enable immediately.

Also, although highly unlikely it’s best to do the seek before starting playback. Since they are atomic operations happening on different threads there is a small chance that the audio thread will play its first buffer from the beginning as it won’t have received the seek call yet.

cheers,
Rich


#5

Thanks, I’ll do that.


#6

As an update, I’ve added a guard (here) so a when time in the past just gets scheduled next processing block. It is part of this PR: https://github.com/cinder/Cinder/pull/1899

Thanks for reporting, and making it easy to reproduce!

cheers,
Rich