Audio Output: Take a more nuclear approach to output resetting when seeking

CQTexperiment
Christopher Snowhill 2021-12-25 23:41:45 -08:00
parent 1278b64afd
commit d22ee14a36
9 changed files with 101 additions and 37 deletions

View File

@ -15,6 +15,8 @@
@interface BufferChain : NSObject { @interface BufferChain : NSObject {
InputNode *inputNode; InputNode *inputNode;
ConverterNode *converterNode; ConverterNode *converterNode;
AudioStreamBasicDescription _inputFormat;
NSURL *streamURL; NSURL *streamURL;
id userInfo; id userInfo;
@ -63,4 +65,7 @@
- (id)controller; - (id)controller;
- (ConverterNode *)converter;
- (AudioStreamBasicDescription)inputFormat;
@end @end

View File

@ -63,7 +63,7 @@
if (![inputNode openWithSource:source]) if (![inputNode openWithSource:source])
return NO; return NO;
if (![converterNode setupWithInputFormat:propertiesToASBD([inputNode properties]) outputFormat:outputFormat]) if (![converterNode setupWithInputFormat:(_inputFormat = propertiesToASBD([inputNode properties])) outputFormat:outputFormat])
return NO; return NO;
[self setRGInfo:rgi]; [self setRGInfo:rgi];
@ -82,7 +82,7 @@
return NO; return NO;
DLog(@"Input Properties: %@", [inputNode properties]); DLog(@"Input Properties: %@", [inputNode properties]);
if (![converterNode setupWithInputFormat:propertiesToASBD([inputNode properties]) outputFormat:outputFormat]) if (![converterNode setupWithInputFormat:(_inputFormat = propertiesToASBD([inputNode properties])) outputFormat:outputFormat])
return NO; return NO;
[self setRGInfo:rgi]; [self setRGInfo:rgi];
@ -199,4 +199,14 @@
return controller; return controller;
} }
- (ConverterNode *)converter
{
return converterNode;
}
- (AudioStreamBasicDescription)inputFormat
{
return _inputFormat;
}
@end @end

View File

@ -22,6 +22,11 @@
void *callbackBuffer; void *callbackBuffer;
size_t callbackBufferSize; size_t callbackBufferSize;
BOOL stopping;
BOOL convertEntered;
BOOL ACInputEntered;
BOOL ACFloatEntered;
float sampleRatio; float sampleRatio;
float volumeScale; float volumeScale;

View File

@ -43,6 +43,11 @@ void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
floatBufferSize = 0; floatBufferSize = 0;
callbackBuffer = NULL; callbackBuffer = NULL;
callbackBufferSize = 0; callbackBufferSize = 0;
stopping = NO;
convertEntered = NO;
ACInputEntered = NO;
ACFloatEntered = NO;
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeScaling" options:0 context:nil]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeScaling" options:0 context:nil];
} }
@ -169,14 +174,16 @@ static OSStatus ACInputProc(AudioConverterRef inAudioConverter,
OSStatus err = noErr; OSStatus err = noErr;
int amountToWrite; int amountToWrite;
int amountRead; int amountRead;
if ([converter shouldContinue] == NO || [converter endOfStream] == YES) if (converter->stopping || [converter shouldContinue] == NO || [converter endOfStream] == YES)
{ {
ioData->mBuffers[0].mDataByteSize = 0; ioData->mBuffers[0].mDataByteSize = 0;
*ioNumberDataPackets = 0; *ioNumberDataPackets = 0;
return noErr; return noErr;
} }
converter->ACInputEntered = YES;
amountToWrite = (*ioNumberDataPackets)*(converter->inputFormat.mBytesPerPacket); amountToWrite = (*ioNumberDataPackets)*(converter->inputFormat.mBytesPerPacket);
@ -188,6 +195,8 @@ static OSStatus ACInputProc(AudioConverterRef inAudioConverter,
{ {
ioData->mBuffers[0].mDataByteSize = 0; ioData->mBuffers[0].mDataByteSize = 0;
*ioNumberDataPackets = 0; *ioNumberDataPackets = 0;
converter->ACInputEntered = NO;
return 100; //Keep asking for data return 100; //Keep asking for data
} }
@ -196,7 +205,9 @@ static OSStatus ACInputProc(AudioConverterRef inAudioConverter,
ioData->mBuffers[0].mDataByteSize = amountRead; ioData->mBuffers[0].mDataByteSize = amountRead;
ioData->mBuffers[0].mNumberChannels = (converter->inputFormat.mChannelsPerFrame); ioData->mBuffers[0].mNumberChannels = (converter->inputFormat.mChannelsPerFrame);
ioData->mNumberBuffers = 1; ioData->mNumberBuffers = 1;
converter->ACInputEntered = NO;
return err; return err;
} }
@ -210,13 +221,15 @@ static OSStatus ACFloatProc(AudioConverterRef inAudioConverter,
OSStatus err = noErr; OSStatus err = noErr;
int amountToWrite; int amountToWrite;
if ([converter shouldContinue] == NO) if (converter->stopping || [converter shouldContinue] == NO)
{ {
ioData->mBuffers[0].mDataByteSize = 0; ioData->mBuffers[0].mDataByteSize = 0;
*ioNumberDataPackets = 0; *ioNumberDataPackets = 0;
return noErr; return noErr;
} }
converter->ACFloatEntered = YES;
amountToWrite = (*ioNumberDataPackets) * (converter->dmFloatFormat.mBytesPerPacket); amountToWrite = (*ioNumberDataPackets) * (converter->dmFloatFormat.mBytesPerPacket);
@ -232,10 +245,15 @@ static OSStatus ACFloatProc(AudioConverterRef inAudioConverter,
ioData->mNumberBuffers = 1; ioData->mNumberBuffers = 1;
if (amountToWrite == 0) if (amountToWrite == 0)
{
converter->ACFloatEntered = NO;
return 100; return 100;
}
converter->floatOffset += amountToWrite; converter->floatOffset += amountToWrite;
converter->ACFloatEntered = NO;
return err; return err;
} }
@ -258,9 +276,15 @@ static OSStatus ACFloatProc(AudioConverterRef inAudioConverter,
int amountReadFromFC; int amountReadFromFC;
int amountRead = 0; int amountRead = 0;
if (stopping)
return 0;
convertEntered = YES;
tryagain2: tryagain2:
if ([self shouldContinue] == NO || [self endOfStream] == YES) if (stopping || [self shouldContinue] == NO || [self endOfStream] == YES)
{ {
convertEntered = NO;
return amountRead; return amountRead;
} }
@ -287,6 +311,12 @@ tryagain2:
ioData.mNumberBuffers = 1; ioData.mNumberBuffers = 1;
tryagain: tryagain:
if (stopping)
{
convertEntered = NO;
return 0;
}
err = AudioConverterFillComplexBuffer(converterFloat, ACInputProc, (__bridge void * _Nullable)(self), &ioNumberPackets, &ioData, NULL); err = AudioConverterFillComplexBuffer(converterFloat, ACInputProc, (__bridge void * _Nullable)(self), &ioNumberPackets, &ioData, NULL);
amountReadFromFC += ioNumberPackets * floatFormat.mBytesPerPacket; amountReadFromFC += ioNumberPackets * floatFormat.mBytesPerPacket;
if (err == 100) if (err == 100)
@ -301,6 +331,7 @@ tryagain2:
else if (err != noErr && err != kAudioConverterErr_InvalidInputSize) else if (err != noErr && err != kAudioConverterErr_InvalidInputSize)
{ {
DLog(@"Error: %i", err); DLog(@"Error: %i", err);
convertEntered = NO;
return amountRead; return amountRead;
} }
@ -335,6 +366,12 @@ tryagain2:
ioData.mBuffers[0].mNumberChannels = outputFormat.mChannelsPerFrame; ioData.mBuffers[0].mNumberChannels = outputFormat.mChannelsPerFrame;
ioData.mNumberBuffers = 1; ioData.mNumberBuffers = 1;
if (stopping)
{
convertEntered = NO;
return 0;
}
err = AudioConverterFillComplexBuffer(converter, ACFloatProc, (__bridge void *)(self), &ioNumberPackets, &ioData, NULL); err = AudioConverterFillComplexBuffer(converter, ACFloatProc, (__bridge void *)(self), &ioNumberPackets, &ioData, NULL);
amountRead += ioNumberPackets * outputFormat.mBytesPerPacket; amountRead += ioNumberPackets * outputFormat.mBytesPerPacket;
if (err == 100) if (err == 100)
@ -345,7 +382,8 @@ tryagain2:
{ {
DLog(@"Error: %i", err); DLog(@"Error: %i", err);
} }
convertEntered = NO;
return amountRead; return amountRead;
} }
@ -414,6 +452,11 @@ static float db_to_scale(float db)
{ {
//Make the converter //Make the converter
OSStatus stat = noErr; OSStatus stat = noErr;
stopping = NO;
convertEntered = NO;
ACInputEntered = NO;
ACFloatEntered = NO;
inputFormat = inf; inputFormat = inf;
outputFormat = outf; outputFormat = outf;
@ -514,6 +557,11 @@ static float db_to_scale(float db)
- (void)inputFormatDidChange:(AudioStreamBasicDescription)format - (void)inputFormatDidChange:(AudioStreamBasicDescription)format
{ {
DLog(@"FORMAT CHANGED"); DLog(@"FORMAT CHANGED");
stopping = YES;
while (convertEntered || ACInputEntered || ACFloatEntered)
{
usleep(500);
}
[self cleanUp]; [self cleanUp];
[self setupWithInputFormat:format outputFormat:outputFormat]; [self setupWithInputFormat:format outputFormat:outputFormat];
} }

View File

@ -122,17 +122,21 @@
if (shouldSeek == YES) if (shouldSeek == YES)
{ {
OutputNode *output = [[controller controller] output]; OutputNode *output = [[controller controller] output];
BOOL isPaused = [output isPaused]; ConverterNode *converter = [[[controller controller] bufferChain] converter];
if ( !isPaused ) [output pause]; DLog(@"SEEKING! Resetting Buffer");
DLog(@"SEEKING!");
seekError = [decoder seek:seekFrame] < 0; [self resetBuffer];
if ( !isPaused ) [output resumeWithFade]; [output reset];
[converter resetBuffer];
[converter inputFormatDidChange:[[[controller controller] bufferChain] inputFormat]];
DLog(@"Reset buffer!");
DLog(@"SEEKING!");
seekError = [decoder seek:seekFrame] < 0;
shouldSeek = NO; shouldSeek = NO;
DLog(@"Seeked! Resetting Buffer"); DLog(@"Seeked! Resetting Buffer");
[self resetBuffer];
DLog(@"Reset buffer!");
initialBufferFilled = NO; initialBufferFilled = NO;
} }

View File

@ -30,6 +30,7 @@
- (void)process; - (void)process;
- (void)close; - (void)close;
- (void)seek:(double)time; - (void)seek:(double)time;
- (void)reset;
- (int)readData:(void *)ptr amount:(int)amount; - (int)readData:(void *)ptr amount:(int)amount;
@ -42,7 +43,6 @@
- (void)pause; - (void)pause;
- (void)resume; - (void)resume;
- (void)resumeWithFade;
- (BOOL)isPaused; - (BOOL)isPaused;

View File

@ -51,10 +51,11 @@
[output resume]; [output resume];
} }
- (void)resumeWithFade - (void)reset
{ {
paused = NO; [output setup];
[output resumeWithFade]; if (!paused)
[output start];
} }
- (int)readData:(void *)ptr amount:(int)amount - (int)readData:(void *)ptr amount:(int)amount

View File

@ -43,7 +43,6 @@
- (void)pause; - (void)pause;
- (void)resume; - (void)resume;
- (void)stop; - (void)stop;
- (void)resumeWithFade;
- (void)setVolume:(double) v; - (void)setVolume:(double) v;

View File

@ -44,10 +44,6 @@ static void Sound_Renderer(void *userData, AudioQueueRef queue, AudioQueueBuffer
if (output->stopping == YES) if (output->stopping == YES)
{ {
// *shrug* At least this will stop it from trying to emit data post-shutdown
memset(readPointer, 0, amountToRead);
buffer->mAudioDataByteSize = amountToRead;
AudioQueueEnqueueBuffer(queue, buffer, 0, NULL);
return; return;
} }
@ -260,6 +256,8 @@ static void Sound_Renderer(void *userData, AudioQueueRef queue, AudioQueueBuffer
{ {
if (outputUnit || audioQueue) if (outputUnit || audioQueue)
[self stop]; [self stop];
stopping = NO;
AudioComponentDescription desc; AudioComponentDescription desc;
OSStatus err; OSStatus err;
@ -375,6 +373,8 @@ static void Sound_Renderer(void *userData, AudioQueueRef queue, AudioQueueBuffer
- (void)start - (void)start
{ {
AudioQueueSetParameter(audioQueue, kAudioQueueParam_VolumeRampTime, 0);
AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, volume);
AudioQueueStart(audioQueue, NULL); AudioQueueStart(audioQueue, NULL);
} }
@ -389,6 +389,9 @@ static void Sound_Renderer(void *userData, AudioQueueRef queue, AudioQueueBuffer
} }
if (audioQueue && buffers) if (audioQueue && buffers)
{ {
AudioQueuePause(audioQueue);
AudioQueueStop(audioQueue, true);
for (UInt32 i = 0; i < numberOfBuffers; ++i) for (UInt32 i = 0; i < numberOfBuffers; ++i)
{ {
if (buffers[i]) if (buffers[i])
@ -414,23 +417,12 @@ static void Sound_Renderer(void *userData, AudioQueueRef queue, AudioQueueBuffer
- (void)pause - (void)pause
{ {
AudioQueueSetParameter(audioQueue, kAudioQueueParam_VolumeRampTime, 0);
AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 0);
AudioQueuePause(audioQueue); AudioQueuePause(audioQueue);
} }
- (void)resume - (void)resume
{ {
AudioQueueStart(audioQueue, NULL); AudioQueueStart(audioQueue, NULL);
AudioQueueSetParameter(audioQueue, kAudioQueueParam_VolumeRampTime, 0);
AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, volume);
}
- (void)resumeWithFade
{
AudioQueueStart(audioQueue, NULL);
AudioQueueSetParameter(audioQueue, kAudioQueueParam_VolumeRampTime, 0.4);
AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, volume);
} }
@end @end