Cog Audio: Implement play position skip ahead when output format changes, based on how much converter output is being discarded

This commit is contained in:
Christopher Snowhill 2022-01-12 23:17:07 -08:00
parent 52b17bd4d8
commit 73348b1616
2 changed files with 17 additions and 11 deletions

View file

@ -18,7 +18,8 @@
@interface OutputNode : Node {
AudioStreamBasicDescription format;
unsigned long long amountPlayed;
double amountPlayed;
double sampleRatio;
OutputCoreAudio *output;
BOOL paused;

View file

@ -17,7 +17,8 @@
- (void)setup
{
amountPlayed = 0;
amountPlayed = 0.0;
sampleRatio = 0.0;
paused = YES;
@ -30,7 +31,7 @@
{
// [output pause];
amountPlayed = time*format.mBytesPerFrame*(format.mSampleRate);
amountPlayed = time;
}
- (void)process
@ -58,11 +59,11 @@
[self setPreviousNode:[[controller bufferChain] finalNode]];
n = [super readData:ptr amount:amount];
amountPlayed += n;
amountPlayed += (double)n * sampleRatio;
if (endOfStream == YES && !n)
{
amountPlayed = 0;
amountPlayed = 0.0;
[controller endOfInputPlayed]; //Updates shouldContinue appropriately?
}
@ -78,7 +79,7 @@
- (double)amountPlayed
{
return (amountPlayed/format.mBytesPerFrame)/(format.mSampleRate);
return amountPlayed;
}
- (AudioStreamBasicDescription) format
@ -89,16 +90,20 @@
- (void)setFormat:(AudioStreamBasicDescription *)f
{
format = *f;
// Calculate a ratio and add to double(seconds) instead, as format may change
double oldSampleRatio = sampleRatio;
sampleRatio = 1.0 / (format.mSampleRate * format.mBytesPerPacket);
BufferChain *bufferChain = [controller bufferChain];
if (bufferChain)
{
InputNode *input = [bufferChain inputNode];
ConverterNode *converter = [bufferChain converter];
if (input && converter)
if (converter)
{
// Need to clear the buffer, as it contains converted output
// targeting the previous output format
[input resetBuffer];
// This clears the resampler buffer, but not the input buffer
// We also have to jump the play position ahead accounting for
// the data we are flushing
if (oldSampleRatio)
amountPlayed += oldSampleRatio * [[converter buffer] bufferedLength];
[converter setOutputFormat:format];
[converter inputFormatDidChange:[bufferChain inputFormat]];
}