Bug Fix: Ensure robust output format changes
Output format mostly requires stopping and restarting the output device, and this also prevents us from using the latency function properly, which apparently always returns 0 for output devices anyway. These changes also prevent the output callback from hanging when resets occur. Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
a3385d1af9
commit
17b8647052
2 changed files with 29 additions and 12 deletions
|
@ -55,6 +55,7 @@ using std::atomic_long;
|
||||||
BOOL paused;
|
BOOL paused;
|
||||||
BOOL restarted;
|
BOOL restarted;
|
||||||
BOOL commandStop;
|
BOOL commandStop;
|
||||||
|
BOOL resetting;
|
||||||
|
|
||||||
BOOL eqEnabled;
|
BOOL eqEnabled;
|
||||||
BOOL eqInitialized;
|
BOOL eqInitialized;
|
||||||
|
|
|
@ -450,6 +450,8 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFormat = [[AVAudioFormat alloc] initWithStreamDescription:&deviceFormat channelLayout:[[AVAudioChannelLayout alloc] initWithLayoutTag:tag]];
|
renderFormat = [[AVAudioFormat alloc] initWithStreamDescription:&deviceFormat channelLayout:[[AVAudioChannelLayout alloc] initWithLayoutTag:tag]];
|
||||||
|
resetting = YES;
|
||||||
|
[_au stopHardware];
|
||||||
[_au.inputBusses[0] setFormat:renderFormat error:&err];
|
[_au.inputBusses[0] setFormat:renderFormat error:&err];
|
||||||
if(err != nil)
|
if(err != nil)
|
||||||
return NO;
|
return NO;
|
||||||
|
@ -459,6 +461,14 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
[outputLock lock];
|
[outputLock lock];
|
||||||
[outputBuffer reset];
|
[outputBuffer reset];
|
||||||
[outputLock unlock];
|
[outputLock unlock];
|
||||||
|
|
||||||
|
if(started) {
|
||||||
|
[_au startHardwareAndReturnError:&err];
|
||||||
|
if(err != nil)
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetting = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
|
@ -569,16 +579,26 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
OutputCoreAudio *_self = (__bridge OutputCoreAudio *)refCon;
|
OutputCoreAudio *_self = (__bridge OutputCoreAudio *)refCon;
|
||||||
int renderedSamples = 0;
|
int renderedSamples = 0;
|
||||||
|
|
||||||
|
if(_self->resetting) {
|
||||||
|
inputData->mBuffers[0].mDataByteSize = frameCount * format->mBytesPerPacket;
|
||||||
|
bzero(inputData->mBuffers[0].mData, inputData->mBuffers[0].mDataByteSize);
|
||||||
|
inputData->mBuffers[0].mNumberChannels = channels;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
while(renderedSamples < frameCount) {
|
while(renderedSamples < frameCount) {
|
||||||
[refLock lock];
|
[refLock lock];
|
||||||
AudioChunk *chunk = [_self->outputBuffer removeSamples:frameCount - renderedSamples];
|
AudioChunk *chunk = nil;
|
||||||
|
if(![_self->outputBuffer isEmpty]) {
|
||||||
|
chunk = [_self->outputBuffer removeSamples:frameCount - renderedSamples];
|
||||||
|
}
|
||||||
[refLock unlock];
|
[refLock unlock];
|
||||||
|
|
||||||
_self->streamTimestamp = [chunk streamTimestamp];
|
if(chunk && [chunk frameCount]) {
|
||||||
|
_self->streamTimestamp = [chunk streamTimestamp];
|
||||||
|
|
||||||
size_t _frameCount = [chunk frameCount];
|
size_t _frameCount = [chunk frameCount];
|
||||||
if(_frameCount) {
|
|
||||||
NSData *sampleData = [chunk removeSamples:_frameCount];
|
NSData *sampleData = [chunk removeSamples:_frameCount];
|
||||||
float *samplePtr = (float *)[sampleData bytes];
|
float *samplePtr = (float *)[sampleData bytes];
|
||||||
size_t inputTodo = MIN(_frameCount, frameCount - renderedSamples);
|
size_t inputTodo = MIN(_frameCount, frameCount - renderedSamples);
|
||||||
|
@ -586,7 +606,7 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
renderedSamples += inputTodo;
|
renderedSamples += inputTodo;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_self->stopping) {
|
if(_self->stopping || _self->resetting) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -708,11 +728,7 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
- (double)latency {
|
- (double)latency {
|
||||||
NSTimeInterval latency = 0.0;
|
return [outputBuffer listDuration];
|
||||||
if(_au) {
|
|
||||||
latency = [_au latency];
|
|
||||||
}
|
|
||||||
return [outputBuffer listDuration] + latency;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)start {
|
- (void)start {
|
||||||
|
|
Loading…
Reference in a new issue