[Audio Threads] Change workgroup system again
Now it allocates audio workgroups per thread, using work slices like the Apple documentation describes for asynchronous threads. Signed-off-by: Christopher Snowhill <kode54@gmail.com>swiftingly
parent
fef8821cf6
commit
91898e9e77
|
@ -430,9 +430,11 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
|
|||
while(paused) {
|
||||
usleep(500);
|
||||
}
|
||||
[self startWorkslice];
|
||||
@autoreleasepool {
|
||||
amountConverted = [self convert:writeBuf amount:CHUNK_SIZE];
|
||||
}
|
||||
[self endWorkslice];
|
||||
if(!amountConverted) {
|
||||
if(paused) {
|
||||
continue;
|
||||
|
|
|
@ -178,9 +178,11 @@
|
|||
|
||||
int framesToRead = CHUNK_SIZE - amountInBuffer;
|
||||
int framesRead;
|
||||
[self startWorkslice];
|
||||
@autoreleasepool {
|
||||
framesRead = [decoder readAudio:((char *)inputBuffer) + bytesInBuffer frames:framesToRead];
|
||||
}
|
||||
[self endWorkslice];
|
||||
|
||||
if(framesRead > 0 && !seekError) {
|
||||
amountInBuffer += framesRead;
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
uint32_t nodeChannelConfig;
|
||||
BOOL nodeLossless;
|
||||
|
||||
os_workgroup_t wg;
|
||||
int64_t intervalMachLength;
|
||||
os_workgroup_interval_t workgroup, wg;
|
||||
os_workgroup_join_token_s wgToken;
|
||||
}
|
||||
- (id _Nullable)initWithController:(id _Nonnull)c previous:(id _Nullable)p;
|
||||
|
@ -49,6 +50,8 @@
|
|||
|
||||
- (void)followWorkgroup;
|
||||
- (void)leaveWorkgroup;
|
||||
- (void)startWorkslice;
|
||||
- (void)endWorkslice;
|
||||
|
||||
- (void)launchThread;
|
||||
|
||||
|
|
|
@ -13,6 +13,20 @@
|
|||
|
||||
#import "OutputCoreAudio.h"
|
||||
|
||||
#import <mach/mach_time.h>
|
||||
|
||||
// This workgroup attribute isn't currently used. Set it to NULL.
|
||||
static os_workgroup_attr_t _Nullable attr = nil;
|
||||
|
||||
// One nanosecond in seconds.
|
||||
static const double kOneNanosecond = 1.0e9;
|
||||
|
||||
// The I/O interval time in seconds.
|
||||
static const double kIOIntervalTime = 0.020;
|
||||
|
||||
// The clock identifier that specifies interval timestamps.
|
||||
static const os_clockid_t clockId = OS_CLOCK_MACH_ABSOLUTE_TIME;
|
||||
|
||||
@implementation Node
|
||||
|
||||
- (id)initWithController:(id)c previous:(id)p {
|
||||
|
@ -32,6 +46,21 @@
|
|||
nodeChannelConfig = 0;
|
||||
nodeLossless = NO;
|
||||
|
||||
if(@available(macOS 11, *)) {
|
||||
workgroup = AudioWorkIntervalCreate("Node Work Interval", clockId, attr);
|
||||
|
||||
// Get the mach time info.
|
||||
struct mach_timebase_info timeBaseInfo;
|
||||
mach_timebase_info(&timeBaseInfo);
|
||||
|
||||
// The frequency of the clock is: (timeBaseInfo.denom / timeBaseInfo.numer) * kOneNanosecond
|
||||
const double nanoSecFrequency = (double)(timeBaseInfo.denom) / (double)(timeBaseInfo.numer);
|
||||
const double frequency = nanoSecFrequency * kOneNanosecond;
|
||||
|
||||
// Convert the interval time in seconds to mach time length.
|
||||
intervalMachLength = (int64_t)(kIOIntervalTime * frequency);
|
||||
}
|
||||
|
||||
[self setPreviousNode:p];
|
||||
}
|
||||
|
||||
|
@ -101,11 +130,8 @@
|
|||
|
||||
- (void)followWorkgroup {
|
||||
if(@available(macOS 11, *)) {
|
||||
if(currentWorkgroup != wg) {
|
||||
if(wg) {
|
||||
os_workgroup_leave(wg, &wgToken);
|
||||
}
|
||||
wg = currentWorkgroup;
|
||||
if(!wg) {
|
||||
wg = workgroup;
|
||||
if(wg) {
|
||||
int result = os_workgroup_join(wg, &wgToken);
|
||||
if(result == 0) return;
|
||||
|
@ -128,6 +154,30 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void)startWorkslice {
|
||||
if(@available(macOS 11, *)) {
|
||||
if(wg) {
|
||||
const uint64_t currentTime = mach_absolute_time();
|
||||
const uint64_t deadline = currentTime + intervalMachLength;
|
||||
int result = os_workgroup_interval_start(wg, currentTime, deadline, nil);
|
||||
if(result != 0) {
|
||||
DLog(@"Deadline error = %d", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)endWorkslice {
|
||||
if(@available(macOS 11, *)) {
|
||||
if(wg) {
|
||||
int result = os_workgroup_interval_finish(wg, nil);
|
||||
if(result != 0) {
|
||||
DLog(@"Deadline end error = %d", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)peekFormat:(nonnull AudioStreamBasicDescription *)format channelConfig:(nonnull uint32_t *)config {
|
||||
[accessLock lock];
|
||||
|
||||
|
|
|
@ -33,10 +33,6 @@ using std::atomic_long;
|
|||
#import <stdio.h>
|
||||
#endif
|
||||
|
||||
#import <os/workgroup.h>
|
||||
|
||||
extern volatile os_workgroup_t currentWorkgroup;
|
||||
|
||||
@class OutputNode;
|
||||
|
||||
@interface OutputCoreAudio : NSObject {
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
#import <Accelerate/Accelerate.h>
|
||||
|
||||
volatile os_workgroup_t currentWorkgroup;
|
||||
|
||||
extern void scale_by_volume(float *buffer, size_t count, float volume);
|
||||
|
||||
static NSString *CogPlaybackDidBeginNotficiation = @"CogPlaybackDidBeginNotficiation";
|
||||
|
@ -263,21 +261,6 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
|||
NSMutableArray *delayedEvents = [[NSMutableArray alloc] init];
|
||||
BOOL delayedEventsPopped = YES;
|
||||
|
||||
if(@available(macOS 11, *)) {
|
||||
if(currentWorkgroup) {
|
||||
wg = currentWorkgroup;
|
||||
int result = os_workgroup_join(wg, &wgToken);
|
||||
if(result != 0) {
|
||||
if(result == EALREADY) {
|
||||
DLog(@"Output thread already in workgroup");
|
||||
} else {
|
||||
DLog(@"Output thread could not be added to workgroup, error = %d", result);
|
||||
}
|
||||
wg = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while(!stopping) {
|
||||
if(++eventCount == 48) {
|
||||
[self resetIfOutputChanged];
|
||||
|
@ -363,13 +346,6 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
|||
[writeSemaphore timedWait:5000];
|
||||
}
|
||||
|
||||
if(@available(macOS 11, *)) {
|
||||
if(wg) {
|
||||
os_workgroup_leave(wg, &wgToken);
|
||||
wg = nil;
|
||||
}
|
||||
}
|
||||
|
||||
stopped = YES;
|
||||
if(!stopInvoked)
|
||||
[self stop];
|
||||
|
@ -806,10 +782,6 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
|||
|
||||
visController = [VisualizationController sharedController];
|
||||
|
||||
if(@available(macOS 11, *)) {
|
||||
currentWorkgroup = _au.osWorkgroup;
|
||||
}
|
||||
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputDevice" options:0 context:NULL];
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.GraphicEQenable" options:0 context:NULL];
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.eqPreamp" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:NULL];
|
||||
|
@ -839,10 +811,6 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
|||
}
|
||||
|
||||
- (void)stop {
|
||||
if(@available(macOS 11, *)) {
|
||||
currentWorkgroup = nil;
|
||||
}
|
||||
|
||||
stopInvoked = YES;
|
||||
if(observersapplied) {
|
||||
observersapplied = NO;
|
||||
|
|
Loading…
Reference in New Issue