Core Audio output: Fix so it stops properly

CQTexperiment
Christopher Snowhill 2022-01-11 20:38:17 -08:00
parent 91c3feac2e
commit 557e0bd399
3 changed files with 20 additions and 25 deletions

View File

@ -60,7 +60,7 @@
n = [super readData:ptr amount:amount]; n = [super readData:ptr amount:amount];
amountPlayed += n; amountPlayed += n;
if (endOfStream == YES) if (endOfStream == YES && !n)
{ {
amountPlayed = 0; amountPlayed = 0;
[controller endOfInputPlayed]; //Updates shouldContinue appropriately? [controller endOfInputPlayed]; //Updates shouldContinue appropriately?

View File

@ -8,6 +8,7 @@
#import <AssertMacros.h> #import <AssertMacros.h>
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import <dispatch/dispatch.h>
#import <CoreAudio/AudioHardware.h> #import <CoreAudio/AudioHardware.h>
#import <AudioToolbox/AudioToolbox.h> #import <AudioToolbox/AudioToolbox.h>
@ -19,12 +20,9 @@
@interface OutputCoreAudio : NSObject { @interface OutputCoreAudio : NSObject {
OutputNode * outputController; OutputNode * outputController;
BOOL running;
BOOL stopping; BOOL stopping;
BOOL stopped; BOOL stopped;
size_t outputSilenceBlocks;
BOOL listenerapplied; BOOL listenerapplied;
float volume; float volume;
@ -34,6 +32,8 @@
AUAudioUnit *_au; AUAudioUnit *_au;
size_t _bufferSize; size_t _bufferSize;
dispatch_semaphore_t sem;
} }
- (id)initWithController:(OutputNode *)c; - (id)initWithController:(OutputNode *)c;

View File

@ -26,7 +26,6 @@ extern void scale_by_volume(float * buffer, size_t count, float volume);
volume = 1.0; volume = 1.0;
outputDeviceID = -1; outputDeviceID = -1;
listenerapplied = NO; listenerapplied = NO;
outputSilenceBlocks = 0;
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputDevice" options:0 context:NULL]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputDevice" options:0 context:NULL];
} }
@ -51,6 +50,13 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
} }
} }
- (void)threadEntry:(id)arg
{
while (!stopping) {
dispatch_semaphore_wait(sem, 500 * USEC_PER_SEC);
}
[self stop];
}
- (OSStatus)setOutputDeviceByID:(AudioDeviceID)deviceID - (OSStatus)setOutputDeviceByID:(AudioDeviceID)deviceID
{ {
@ -224,9 +230,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
[self stop]; [self stop];
stopping = NO; stopping = NO;
stopped = NO;
outputDeviceID = -1; outputDeviceID = -1;
outputSilenceBlocks = 0;
AVAudioFormat *format, *renderFormat; AVAudioFormat *format, *renderFormat;
AudioComponentDescription desc; AudioComponentDescription desc;
@ -320,21 +324,12 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
amountToRead = framesToRead * (self->deviceFormat.mBytesPerPacket); amountToRead = framesToRead * (self->deviceFormat.mBytesPerPacket);
if (self->outputSilenceBlocks || self->stopping == YES) if (self->stopping == YES || [self->outputController shouldContinue] == NO)
{ {
memset(readPointer, 0, amountToRead); memset(readPointer, 0, amountToRead);
inputData->mBuffers[0].mDataByteSize = amountToRead; inputData->mBuffers[0].mDataByteSize = amountToRead;
if (self->outputSilenceBlocks && self->stopping = YES;
--self->outputSilenceBlocks == 0) dispatch_semaphore_signal(weakSelf->sem);
[weakSelf stop];
return 0;
}
if ([self->outputController shouldContinue] == NO)
{
memset(readPointer, 0, amountToRead);
inputData->mBuffers[0].mDataByteSize = amountToRead;
self->outputSilenceBlocks = 48;
return 0; return 0;
} }
@ -366,6 +361,9 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
[_au allocateRenderResourcesAndReturnError:&err]; [_au allocateRenderResourcesAndReturnError:&err];
sem = dispatch_semaphore_create(0);
[NSThread detachNewThreadSelector:@selector(threadEntry:) toTarget:self withObject:nil];
[outputController setFormat:&deviceFormat]; [outputController setFormat:&deviceFormat];
return (err == nil); return (err == nil);
@ -380,12 +378,10 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
{ {
NSError *err; NSError *err;
[_au startHardwareAndReturnError:&err]; [_au startHardwareAndReturnError:&err];
running = YES;
} }
- (void)stop - (void)stop
{ {
stopping = YES;
if (listenerapplied) { if (listenerapplied) {
AudioObjectPropertyAddress theAddress = { AudioObjectPropertyAddress theAddress = {
.mSelector = kAudioHardwarePropertyDefaultOutputDevice, .mSelector = kAudioHardwarePropertyDefaultOutputDevice,
@ -397,8 +393,9 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
} }
if (_au) { if (_au) {
[_au stopHardware]; [_au stopHardware];
running = NO;
_au = nil; _au = nil;
stopping = YES;
dispatch_semaphore_signal(sem);
} }
} }
@ -412,14 +409,12 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
- (void)pause - (void)pause
{ {
[_au stopHardware]; [_au stopHardware];
running = NO;
} }
- (void)resume - (void)resume
{ {
NSError *err; NSError *err;
[_au startHardwareAndReturnError:&err]; [_au startHardwareAndReturnError:&err];
running = YES;
} }
@end @end