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:
parent
52b17bd4d8
commit
73348b1616
2 changed files with 17 additions and 11 deletions
|
@ -18,7 +18,8 @@
|
||||||
@interface OutputNode : Node {
|
@interface OutputNode : Node {
|
||||||
AudioStreamBasicDescription format;
|
AudioStreamBasicDescription format;
|
||||||
|
|
||||||
unsigned long long amountPlayed;
|
double amountPlayed;
|
||||||
|
double sampleRatio;
|
||||||
OutputCoreAudio *output;
|
OutputCoreAudio *output;
|
||||||
|
|
||||||
BOOL paused;
|
BOOL paused;
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
|
|
||||||
- (void)setup
|
- (void)setup
|
||||||
{
|
{
|
||||||
amountPlayed = 0;
|
amountPlayed = 0.0;
|
||||||
|
sampleRatio = 0.0;
|
||||||
|
|
||||||
paused = YES;
|
paused = YES;
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@
|
||||||
{
|
{
|
||||||
// [output pause];
|
// [output pause];
|
||||||
|
|
||||||
amountPlayed = time*format.mBytesPerFrame*(format.mSampleRate);
|
amountPlayed = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)process
|
- (void)process
|
||||||
|
@ -58,11 +59,11 @@
|
||||||
[self setPreviousNode:[[controller bufferChain] finalNode]];
|
[self setPreviousNode:[[controller bufferChain] finalNode]];
|
||||||
|
|
||||||
n = [super readData:ptr amount:amount];
|
n = [super readData:ptr amount:amount];
|
||||||
amountPlayed += n;
|
amountPlayed += (double)n * sampleRatio;
|
||||||
|
|
||||||
if (endOfStream == YES && !n)
|
if (endOfStream == YES && !n)
|
||||||
{
|
{
|
||||||
amountPlayed = 0;
|
amountPlayed = 0.0;
|
||||||
[controller endOfInputPlayed]; //Updates shouldContinue appropriately?
|
[controller endOfInputPlayed]; //Updates shouldContinue appropriately?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +79,7 @@
|
||||||
|
|
||||||
- (double)amountPlayed
|
- (double)amountPlayed
|
||||||
{
|
{
|
||||||
return (amountPlayed/format.mBytesPerFrame)/(format.mSampleRate);
|
return amountPlayed;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (AudioStreamBasicDescription) format
|
- (AudioStreamBasicDescription) format
|
||||||
|
@ -89,16 +90,20 @@
|
||||||
- (void)setFormat:(AudioStreamBasicDescription *)f
|
- (void)setFormat:(AudioStreamBasicDescription *)f
|
||||||
{
|
{
|
||||||
format = *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];
|
BufferChain *bufferChain = [controller bufferChain];
|
||||||
if (bufferChain)
|
if (bufferChain)
|
||||||
{
|
{
|
||||||
InputNode *input = [bufferChain inputNode];
|
|
||||||
ConverterNode *converter = [bufferChain converter];
|
ConverterNode *converter = [bufferChain converter];
|
||||||
if (input && converter)
|
if (converter)
|
||||||
{
|
{
|
||||||
// Need to clear the buffer, as it contains converted output
|
// This clears the resampler buffer, but not the input buffer
|
||||||
// targeting the previous output format
|
// We also have to jump the play position ahead accounting for
|
||||||
[input resetBuffer];
|
// the data we are flushing
|
||||||
|
if (oldSampleRatio)
|
||||||
|
amountPlayed += oldSampleRatio * [[converter buffer] bufferedLength];
|
||||||
[converter setOutputFormat:format];
|
[converter setOutputFormat:format];
|
||||||
[converter inputFormatDidChange:[bufferChain inputFormat]];
|
[converter inputFormatDidChange:[bufferChain inputFormat]];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue