Simplify HRTF filter, change option to reflect it
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
919661c9e8
commit
4ddca15a8f
7 changed files with 133 additions and 436 deletions
|
@ -12,26 +12,15 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface HeadphoneFilter : NSObject {
|
||||
vDSP_DFT_Setup dftSetupF;
|
||||
vDSP_DFT_Setup dftSetupB;
|
||||
|
||||
int fftSize;
|
||||
int fftSizeOver2;
|
||||
int bufferSize;
|
||||
int paddedBufferSize;
|
||||
int channelCount;
|
||||
|
||||
DSPSplitComplex signal_fft;
|
||||
DSPSplitComplex input_filtered_signal_per_channel[2];
|
||||
DSPSplitComplex input_filtered_signal_totals[2];
|
||||
DSPSplitComplex *impulse_responses;
|
||||
|
||||
float **mirroredImpulseResponses;
|
||||
|
||||
float **prevInputs;
|
||||
|
||||
float *left_result;
|
||||
float *right_result;
|
||||
|
||||
float *paddedSignal;
|
||||
float *paddedSignal[2];
|
||||
}
|
||||
|
||||
+ (BOOL)validateImpulseFile:(NSURL *)url;
|
||||
|
|
|
@ -49,200 +49,59 @@ static const speakerPosition speakerPositions[18] = {
|
|||
{ .elevation = DEGREES(+45.0), .azimuth = DEGREES(+135.0), .distance = 1.0 }
|
||||
};
|
||||
|
||||
@interface impulseCacheObject : NSObject {
|
||||
}
|
||||
@property NSURL *URL;
|
||||
@property int sampleCount;
|
||||
@property int channelCount;
|
||||
@property uint32_t channelConfig;
|
||||
@property double sampleRate;
|
||||
@property double targetSampleRate;
|
||||
@property NSData *data;
|
||||
@end
|
||||
|
||||
@implementation impulseCacheObject
|
||||
@synthesize URL;
|
||||
@synthesize sampleCount;
|
||||
@synthesize channelCount;
|
||||
@synthesize channelConfig;
|
||||
@synthesize sampleRate;
|
||||
@synthesize targetSampleRate;
|
||||
@synthesize data;
|
||||
@end
|
||||
|
||||
@interface impulseCache : NSObject {
|
||||
}
|
||||
@property NSMutableArray<impulseCacheObject *> *cacheObjects;
|
||||
+ (impulseCache *)sharedController;
|
||||
- (const float *)getImpulse:(NSURL *)url sampleCount:(int *)sampleCount channelCount:(int)channelCount channelConfig:(uint32_t)channelConfig sampleRate:(double)sampleRate;
|
||||
@end
|
||||
|
||||
// Apparently _mm_malloc is Intel-only on newer macOS targets, so use supported posix_memalign
|
||||
static void *_memalign_malloc(size_t size, size_t align) {
|
||||
void *ret = NULL;
|
||||
if(posix_memalign(&ret, align, size) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@implementation impulseCache
|
||||
|
||||
static impulseCache *_sharedController = nil;
|
||||
|
||||
+ (impulseCache *)sharedController {
|
||||
@synchronized(self) {
|
||||
if(!_sharedController) {
|
||||
_sharedController = [[impulseCache alloc] init];
|
||||
}
|
||||
}
|
||||
return _sharedController;
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if(self) {
|
||||
self.cacheObjects = [[NSMutableArray alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (impulseCacheObject *)addImpulse:(NSURL *)url sampleCount:(int)sampleCount channelCount:(int)channelCount channelConfig:(uint32_t)channelConfig originalSampleRate:(double)originalSampleRate targetSampleRate:(double)targetSampleRate impulseBuffer:(const float *)impulseBuffer {
|
||||
impulseCacheObject *obj = [[impulseCacheObject alloc] init];
|
||||
|
||||
obj.URL = url;
|
||||
obj.sampleCount = sampleCount;
|
||||
obj.channelCount = channelCount;
|
||||
obj.sampleRate = originalSampleRate;
|
||||
obj.targetSampleRate = targetSampleRate;
|
||||
obj.data = [NSData dataWithBytes:impulseBuffer length:(sampleCount * channelCount * sizeof(float) * 2)];
|
||||
|
||||
@synchronized(self.cacheObjects) {
|
||||
[self.cacheObjects addObject:obj];
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
- (const float *)getImpulse:(NSURL *)url sampleCount:(int *)retSampleCount channelCount:(int)channelCount channelConfig:(uint32_t)channelConfig sampleRate:(double)sampleRate {
|
||||
void getImpulse(NSURL *url, float **outImpulse, int *outSampleCount, int channelCount, uint32_t channelConfig) {
|
||||
BOOL impulseFound = NO;
|
||||
const float *impulseData = NULL;
|
||||
double sampleRateOfSource = 0;
|
||||
int sampleCount = 0;
|
||||
impulseCacheObject *cacheObject = nil;
|
||||
|
||||
@synchronized(self.cacheObjects) {
|
||||
for(impulseCacheObject *obj in self.cacheObjects) {
|
||||
if([obj.URL isEqualTo:url] &&
|
||||
obj.targetSampleRate == sampleRate &&
|
||||
obj.channelCount == channelCount &&
|
||||
obj.channelConfig == channelConfig) {
|
||||
*retSampleCount = obj.sampleCount;
|
||||
return (const float *)[obj.data bytes];
|
||||
}
|
||||
}
|
||||
for(impulseCacheObject *obj in self.cacheObjects) {
|
||||
if([obj.URL isEqualTo:url] &&
|
||||
obj.sampleRate == obj.targetSampleRate &&
|
||||
obj.channelCount == channelCount &&
|
||||
obj.channelConfig == channelConfig) {
|
||||
impulseData = (const float *)[obj.data bytes];
|
||||
sampleCount = obj.sampleCount;
|
||||
sampleRateOfSource = obj.sampleRate;
|
||||
impulseFound = YES;
|
||||
break;
|
||||
NSString *filePath = [url path];
|
||||
|
||||
try {
|
||||
std::ifstream file([filePath UTF8String], std::fstream::binary);
|
||||
|
||||
if(!file.is_open()) {
|
||||
throw std::logic_error("Cannot open file.");
|
||||
}
|
||||
|
||||
HrtfData data(file);
|
||||
|
||||
file.close();
|
||||
|
||||
sampleRateOfSource = data.get_sample_rate();
|
||||
|
||||
uint32_t sampleCountExact = data.get_response_length();
|
||||
sampleCount = sampleCountExact + ((data.get_longest_delay() + 2) >> 2);
|
||||
sampleCount = (sampleCount + 15) & ~15;
|
||||
|
||||
*outImpulse = (float *)calloc(sizeof(float), sampleCount * channelCount * 2);
|
||||
if(!*outImpulse) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
float *hrtfData = *outImpulse;
|
||||
|
||||
for(uint32_t i = 0; i < channelCount; ++i) {
|
||||
uint32_t channelFlag = [AudioChunk extractChannelFlag:i fromConfig:channelConfig];
|
||||
uint32_t channelNumber = [AudioChunk findChannelIndex:channelFlag];
|
||||
|
||||
if(channelNumber < 18) {
|
||||
const speakerPosition &speaker = speakerPositions[channelNumber];
|
||||
DirectionData hrtfLeft;
|
||||
DirectionData hrtfRight;
|
||||
|
||||
data.get_direction_data(speaker.elevation, speaker.azimuth, speaker.distance, hrtfLeft, hrtfRight);
|
||||
|
||||
cblas_scopy(sampleCountExact, &hrtfLeft.impulse_response[0], 1, &hrtfData[((hrtfLeft.delay + 2) >> 2) + sampleCount * i * 2], 1);
|
||||
cblas_scopy(sampleCountExact, &hrtfRight.impulse_response[0], 1, &hrtfData[((hrtfLeft.delay + 2) >> 2) + sampleCount * (i * 2 + 1)], 1);
|
||||
}
|
||||
}
|
||||
|
||||
*outSampleCount = sampleCount;
|
||||
} catch(std::exception &e) {
|
||||
ALog(@"Exception caught: %s", e.what());
|
||||
}
|
||||
|
||||
if(!impulseFound) {
|
||||
NSString *filePath = [url path];
|
||||
|
||||
try {
|
||||
std::ifstream file([filePath UTF8String], std::fstream::binary);
|
||||
|
||||
if(!file.is_open()) {
|
||||
throw std::logic_error("Cannot open file.");
|
||||
}
|
||||
|
||||
HrtfData data(file);
|
||||
|
||||
file.close();
|
||||
|
||||
sampleRateOfSource = data.get_sample_rate();
|
||||
|
||||
uint32_t sampleCountExact = data.get_response_length();
|
||||
sampleCount = sampleCountExact + ((data.get_longest_delay() + 2) >> 2);
|
||||
|
||||
std::vector<float> hrtfData(sampleCount * channelCount * 2, 0.0);
|
||||
|
||||
for(uint32_t i = 0; i < channelCount; ++i) {
|
||||
uint32_t channelFlag = [AudioChunk extractChannelFlag:i fromConfig:channelConfig];
|
||||
uint32_t channelNumber = [AudioChunk findChannelIndex:channelFlag];
|
||||
|
||||
if(channelNumber < 18) {
|
||||
const speakerPosition &speaker = speakerPositions[channelNumber];
|
||||
DirectionData hrtfLeft;
|
||||
DirectionData hrtfRight;
|
||||
|
||||
data.get_direction_data(speaker.elevation, speaker.azimuth, speaker.distance, hrtfLeft, hrtfRight);
|
||||
|
||||
cblas_scopy(sampleCountExact, &hrtfLeft.impulse_response[0], 1, &hrtfData[((hrtfLeft.delay + 2) >> 2) * channelCount * 2 + i * 2], channelCount * 2);
|
||||
cblas_scopy(sampleCountExact, &hrtfRight.impulse_response[0], 1, &hrtfData[((hrtfLeft.delay + 2) >> 2) * channelCount * 2 + i * 2 + 1], channelCount * 2);
|
||||
}
|
||||
}
|
||||
|
||||
cacheObject = [self addImpulse:url sampleCount:sampleCount channelCount:channelCount channelConfig:channelConfig originalSampleRate:sampleRateOfSource targetSampleRate:sampleRateOfSource impulseBuffer:&hrtfData[0]];
|
||||
|
||||
impulseData = (const float *)[cacheObject.data bytes];
|
||||
} catch(std::exception &e) {
|
||||
ALog(@"Exception caught: %s", e.what());
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
if(sampleRateOfSource != sampleRate) {
|
||||
double sampleRatio = sampleRate / sampleRateOfSource;
|
||||
int resampledCount = (int)ceil((double)sampleCount * sampleRatio);
|
||||
|
||||
void *rsstate = rsstate_new(channelCount * 2, sampleRateOfSource, sampleRate);
|
||||
|
||||
float *resampledImpulse = (float *)_memalign_malloc(resampledCount * sizeof(float) * channelCount * 2, 16);
|
||||
if(!resampledImpulse) {
|
||||
rsstate_delete(rsstate);
|
||||
return nil;
|
||||
}
|
||||
|
||||
size_t inputDone = 0;
|
||||
size_t outputDone = 0;
|
||||
|
||||
outputDone = rsstate_resample(rsstate, impulseData, sampleCount, &inputDone, resampledImpulse, resampledCount);
|
||||
|
||||
while(outputDone < resampledCount) {
|
||||
outputDone += rsstate_flush(rsstate, resampledImpulse + outputDone * channelCount * 2, resampledCount - outputDone);
|
||||
}
|
||||
|
||||
rsstate_delete(rsstate);
|
||||
|
||||
sampleCount = (int)outputDone;
|
||||
|
||||
// Normalize resampled impulse by sample ratio
|
||||
float fSampleRatio = (float)sampleRatio;
|
||||
vDSP_vsdiv(resampledImpulse, 1, &fSampleRatio, resampledImpulse, 1, sampleCount * channelCount * 2);
|
||||
|
||||
cacheObject = [self addImpulse:url sampleCount:sampleCount channelCount:channelCount channelConfig:channelConfig originalSampleRate:sampleRateOfSource targetSampleRate:sampleRate impulseBuffer:resampledImpulse];
|
||||
|
||||
free(resampledImpulse);
|
||||
|
||||
impulseData = (const float *)[cacheObject.data bytes];
|
||||
}
|
||||
|
||||
*retSampleCount = sampleCount;
|
||||
return impulseData;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation HeadphoneFilter
|
||||
|
||||
+ (BOOL)validateImpulseFile:(NSURL *)url {
|
||||
|
@ -270,132 +129,42 @@ static impulseCache *_sharedController = nil;
|
|||
self = [super init];
|
||||
|
||||
if(self) {
|
||||
float *impulseBuffer = NULL;
|
||||
int sampleCount = 0;
|
||||
const float *impulseBuffer = [[impulseCache sharedController] getImpulse:url sampleCount:&sampleCount channelCount:channels channelConfig:config sampleRate:sampleRate];
|
||||
getImpulse(url, &impulseBuffer, &sampleCount, channels, config);
|
||||
if(!impulseBuffer) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
channelCount = channels;
|
||||
|
||||
bufferSize = 512;
|
||||
fftSize = sampleCount + bufferSize;
|
||||
|
||||
int pow = 1;
|
||||
while(fftSize > 2) {
|
||||
pow++;
|
||||
fftSize /= 2;
|
||||
}
|
||||
fftSize = 2 << pow;
|
||||
|
||||
float *deinterleavedImpulseBuffer = (float *)_memalign_malloc(fftSize * sizeof(float) * channelCount * 2, 16);
|
||||
if(!deinterleavedImpulseBuffer) {
|
||||
mirroredImpulseResponses = (float **)calloc(sizeof(float *), channelCount * 2);
|
||||
if(!mirroredImpulseResponses) {
|
||||
free(impulseBuffer);
|
||||
return nil;
|
||||
}
|
||||
|
||||
for(int i = 0; i < channelCount; ++i) {
|
||||
cblas_scopy(sampleCount, impulseBuffer + i * 2, (int)channelCount * 2, deinterleavedImpulseBuffer + i * fftSize * 2, 1);
|
||||
vDSP_vclr(deinterleavedImpulseBuffer + i * fftSize * 2 + sampleCount, 1, fftSize - sampleCount);
|
||||
cblas_scopy(sampleCount, impulseBuffer + i * 2 + 1, (int)channelCount * 2, deinterleavedImpulseBuffer + i * fftSize * 2 + fftSize, 1);
|
||||
vDSP_vclr(deinterleavedImpulseBuffer + i * fftSize * 2 + fftSize + sampleCount, 1, fftSize - sampleCount);
|
||||
for(int i = 0; i < channelCount * 2; ++i) {
|
||||
mirroredImpulseResponses[i] = &impulseBuffer[sampleCount * i];
|
||||
vDSP_vrvrs(mirroredImpulseResponses[i], 1, sampleCount);
|
||||
}
|
||||
|
||||
paddedBufferSize = fftSize;
|
||||
fftSizeOver2 = (fftSize + 1) / 2;
|
||||
const int fftSizeOver2Plus1 = fftSizeOver2 + 1; // DFT float overwrites plus one, double doesn't
|
||||
paddedBufferSize = sampleCount;
|
||||
|
||||
dftSetupF = vDSP_DFT_zrop_CreateSetup(nil, fftSize, vDSP_DFT_FORWARD);
|
||||
dftSetupB = vDSP_DFT_zrop_CreateSetup(nil, fftSize, vDSP_DFT_INVERSE);
|
||||
if(!dftSetupF || !dftSetupB) {
|
||||
free(deinterleavedImpulseBuffer);
|
||||
paddedSignal[0] = (float *)calloc(sizeof(float), paddedBufferSize * 2);
|
||||
if(!paddedSignal[0]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
paddedSignal = (float *)_memalign_malloc(sizeof(float) * paddedBufferSize, 16);
|
||||
if(!paddedSignal) {
|
||||
free(deinterleavedImpulseBuffer);
|
||||
return nil;
|
||||
}
|
||||
|
||||
signal_fft.realp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
signal_fft.imagp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
if(!signal_fft.realp || !signal_fft.imagp) {
|
||||
free(deinterleavedImpulseBuffer);
|
||||
return nil;
|
||||
}
|
||||
|
||||
input_filtered_signal_per_channel[0].realp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
input_filtered_signal_per_channel[0].imagp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
if(!input_filtered_signal_per_channel[0].realp ||
|
||||
!input_filtered_signal_per_channel[0].imagp) {
|
||||
free(deinterleavedImpulseBuffer);
|
||||
return nil;
|
||||
}
|
||||
|
||||
input_filtered_signal_per_channel[1].realp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
input_filtered_signal_per_channel[1].imagp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
if(!input_filtered_signal_per_channel[1].realp ||
|
||||
!input_filtered_signal_per_channel[1].imagp) {
|
||||
free(deinterleavedImpulseBuffer);
|
||||
return nil;
|
||||
}
|
||||
|
||||
input_filtered_signal_totals[0].realp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
input_filtered_signal_totals[0].imagp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
if(!input_filtered_signal_totals[0].realp ||
|
||||
!input_filtered_signal_totals[0].imagp) {
|
||||
free(deinterleavedImpulseBuffer);
|
||||
return nil;
|
||||
}
|
||||
|
||||
input_filtered_signal_totals[1].realp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
input_filtered_signal_totals[1].imagp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
if(!input_filtered_signal_totals[1].realp ||
|
||||
!input_filtered_signal_totals[1].imagp) {
|
||||
free(deinterleavedImpulseBuffer);
|
||||
return nil;
|
||||
}
|
||||
|
||||
impulse_responses = (DSPSplitComplex *)calloc(sizeof(DSPSplitComplex), channels * 2);
|
||||
if(!impulse_responses) {
|
||||
free(deinterleavedImpulseBuffer);
|
||||
return nil;
|
||||
}
|
||||
|
||||
for(int i = 0; i < channels; ++i) {
|
||||
impulse_responses[i * 2 + 0].realp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
impulse_responses[i * 2 + 0].imagp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
impulse_responses[i * 2 + 1].realp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
impulse_responses[i * 2 + 1].imagp = (float *)_memalign_malloc(sizeof(float) * fftSizeOver2Plus1, 16);
|
||||
|
||||
if(!impulse_responses[i * 2 + 0].realp || !impulse_responses[i * 2 + 0].imagp ||
|
||||
!impulse_responses[i * 2 + 1].realp || !impulse_responses[i * 2 + 1].imagp) {
|
||||
free(deinterleavedImpulseBuffer);
|
||||
return nil;
|
||||
}
|
||||
|
||||
vDSP_ctoz((DSPComplex *)(deinterleavedImpulseBuffer + i * fftSize * 2), 2, &impulse_responses[i * 2 + 0], 1, fftSizeOver2);
|
||||
vDSP_ctoz((DSPComplex *)(deinterleavedImpulseBuffer + i * fftSize * 2 + fftSize), 2, &impulse_responses[i * 2 + 1], 1, fftSizeOver2);
|
||||
|
||||
vDSP_DFT_Execute(dftSetupF, impulse_responses[i * 2 + 0].realp, impulse_responses[i * 2 + 0].imagp, impulse_responses[i * 2 + 0].realp, impulse_responses[i * 2 + 0].imagp);
|
||||
vDSP_DFT_Execute(dftSetupF, impulse_responses[i * 2 + 1].realp, impulse_responses[i * 2 + 1].imagp, impulse_responses[i * 2 + 1].realp, impulse_responses[i * 2 + 1].imagp);
|
||||
}
|
||||
|
||||
free(deinterleavedImpulseBuffer);
|
||||
|
||||
left_result = (float *)_memalign_malloc(sizeof(float) * fftSize, 16);
|
||||
right_result = (float *)_memalign_malloc(sizeof(float) * fftSize, 16);
|
||||
if(!left_result || !right_result)
|
||||
return nil;
|
||||
paddedSignal[1] = paddedSignal[0] + paddedBufferSize;
|
||||
|
||||
prevInputs = (float **)calloc(channels, sizeof(float *));
|
||||
if(!prevInputs)
|
||||
return nil;
|
||||
for(int i = 0; i < channels; ++i) {
|
||||
prevInputs[i] = (float *)_memalign_malloc(sizeof(float) * fftSize, 16);
|
||||
if(!prevInputs[i])
|
||||
return nil;
|
||||
vDSP_vclr(prevInputs[i], 1, fftSize);
|
||||
prevInputs[0] = (float *)calloc(sizeof(float), sampleCount * channelCount);
|
||||
if(!prevInputs[0])
|
||||
return nil;
|
||||
for(int i = 1; i < channels; ++i) {
|
||||
prevInputs[i] = prevInputs[i - 1] + sampleCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,113 +172,52 @@ static impulseCache *_sharedController = nil;
|
|||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if(dftSetupF) vDSP_DFT_DestroySetup(dftSetupF);
|
||||
if(dftSetupB) vDSP_DFT_DestroySetup(dftSetupB);
|
||||
|
||||
free(paddedSignal);
|
||||
|
||||
free(signal_fft.realp);
|
||||
free(signal_fft.imagp);
|
||||
|
||||
free(input_filtered_signal_per_channel[0].realp);
|
||||
free(input_filtered_signal_per_channel[0].imagp);
|
||||
free(input_filtered_signal_per_channel[1].realp);
|
||||
free(input_filtered_signal_per_channel[1].imagp);
|
||||
|
||||
free(input_filtered_signal_totals[0].realp);
|
||||
free(input_filtered_signal_totals[0].imagp);
|
||||
free(input_filtered_signal_totals[1].realp);
|
||||
free(input_filtered_signal_totals[1].imagp);
|
||||
|
||||
if(impulse_responses) {
|
||||
for(int i = 0; i < channelCount * 2; ++i) {
|
||||
free(impulse_responses[i].realp);
|
||||
free(impulse_responses[i].imagp);
|
||||
}
|
||||
free(impulse_responses);
|
||||
if(paddedSignal[0]) {
|
||||
free(paddedSignal[0]);
|
||||
}
|
||||
|
||||
free(left_result);
|
||||
free(right_result);
|
||||
|
||||
if(prevInputs) {
|
||||
for(int i = 0; i < channelCount; ++i) {
|
||||
free(prevInputs[i]);
|
||||
if(prevInputs[0]) {
|
||||
free(prevInputs[0]);
|
||||
}
|
||||
free(prevInputs);
|
||||
}
|
||||
|
||||
if(mirroredImpulseResponses) {
|
||||
if(mirroredImpulseResponses[0]) {
|
||||
free(mirroredImpulseResponses[0]);
|
||||
}
|
||||
free(mirroredImpulseResponses);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)process:(const float *)inBuffer sampleCount:(int)count toBuffer:(float *)outBuffer {
|
||||
const float scale = 1.0 / (4.0 * (float)fftSize);
|
||||
|
||||
int sampleCount = paddedBufferSize;
|
||||
while(count > 0) {
|
||||
const int countToDo = (count > bufferSize) ? bufferSize : count;
|
||||
const int prevToDo = fftSize - countToDo;
|
||||
|
||||
vDSP_vclr(input_filtered_signal_totals[0].realp, 1, fftSizeOver2);
|
||||
vDSP_vclr(input_filtered_signal_totals[0].imagp, 1, fftSizeOver2);
|
||||
vDSP_vclr(input_filtered_signal_totals[1].realp, 1, fftSizeOver2);
|
||||
vDSP_vclr(input_filtered_signal_totals[1].imagp, 1, fftSizeOver2);
|
||||
|
||||
float left = 0, right = 0;
|
||||
for(int i = 0; i < channelCount; ++i) {
|
||||
cblas_scopy((int)prevToDo, prevInputs[i] + countToDo, 1, paddedSignal, 1);
|
||||
cblas_scopy((int)countToDo, inBuffer + i, (int)channelCount, paddedSignal + prevToDo, 1);
|
||||
cblas_scopy((int)fftSize, paddedSignal, 1, prevInputs[i], 1);
|
||||
float thisleft, thisright;
|
||||
vDSP_vmul(prevInputs[i], 1, mirroredImpulseResponses[i * 2], 1, paddedSignal[0], 1, sampleCount);
|
||||
vDSP_vmul(prevInputs[i], 1, mirroredImpulseResponses[i * 2 + 1], 1, paddedSignal[1], 1, sampleCount);
|
||||
vDSP_sve(paddedSignal[0], 1, &thisleft, sampleCount);
|
||||
vDSP_sve(paddedSignal[1], 1, &thisright, sampleCount);
|
||||
left += thisleft;
|
||||
right += thisright;
|
||||
|
||||
vDSP_ctoz((DSPComplex *)paddedSignal, 2, &signal_fft, 1, fftSizeOver2);
|
||||
|
||||
vDSP_DFT_Execute(dftSetupF, signal_fft.realp, signal_fft.imagp, signal_fft.realp, signal_fft.imagp);
|
||||
|
||||
// One channel forward, then multiply and back twice
|
||||
|
||||
float preserveIRNyq = impulse_responses[i * 2 + 0].imagp[0];
|
||||
float preserveSigNyq = signal_fft.imagp[0];
|
||||
impulse_responses[i * 2 + 0].imagp[0] = 0;
|
||||
signal_fft.imagp[0] = 0;
|
||||
|
||||
vDSP_zvmul(&signal_fft, 1, &impulse_responses[i * 2 + 0], 1, &input_filtered_signal_per_channel[0], 1, fftSizeOver2, 1);
|
||||
|
||||
input_filtered_signal_per_channel[0].imagp[0] = preserveIRNyq * preserveSigNyq;
|
||||
impulse_responses[i * 2 + 0].imagp[0] = preserveIRNyq;
|
||||
|
||||
preserveIRNyq = impulse_responses[i * 2 + 1].imagp[0];
|
||||
impulse_responses[i * 2 + 1].imagp[0] = 0;
|
||||
|
||||
vDSP_zvmul(&signal_fft, 1, &impulse_responses[i * 2 + 1], 1, &input_filtered_signal_per_channel[1], 1, fftSizeOver2, 1);
|
||||
|
||||
input_filtered_signal_per_channel[1].imagp[0] = preserveIRNyq * preserveSigNyq;
|
||||
impulse_responses[i * 2 + 1].imagp[0] = preserveIRNyq;
|
||||
|
||||
vDSP_zvadd(&input_filtered_signal_totals[0], 1, &input_filtered_signal_per_channel[0], 1, &input_filtered_signal_totals[0], 1, fftSizeOver2);
|
||||
vDSP_zvadd(&input_filtered_signal_totals[1], 1, &input_filtered_signal_per_channel[1], 1, &input_filtered_signal_totals[1], 1, fftSizeOver2);
|
||||
memmove(prevInputs[i], prevInputs[i] + 1, sizeof(float) * (sampleCount - 1));
|
||||
prevInputs[i][sampleCount - 1] = *inBuffer++;
|
||||
}
|
||||
|
||||
vDSP_DFT_Execute(dftSetupB, input_filtered_signal_totals[0].realp, input_filtered_signal_totals[0].imagp, input_filtered_signal_totals[0].realp, input_filtered_signal_totals[0].imagp);
|
||||
vDSP_DFT_Execute(dftSetupB, input_filtered_signal_totals[1].realp, input_filtered_signal_totals[1].imagp, input_filtered_signal_totals[1].realp, input_filtered_signal_totals[1].imagp);
|
||||
|
||||
vDSP_ztoc(&input_filtered_signal_totals[0], 1, (DSPComplex *)left_result, 2, fftSizeOver2);
|
||||
vDSP_ztoc(&input_filtered_signal_totals[1], 1, (DSPComplex *)right_result, 2, fftSizeOver2);
|
||||
|
||||
float *left_ptr = left_result + prevToDo;
|
||||
float *right_ptr = right_result + prevToDo;
|
||||
|
||||
vDSP_vsmul(left_ptr, 1, &scale, left_ptr, 1, countToDo);
|
||||
vDSP_vsmul(right_ptr, 1, &scale, right_ptr, 1, countToDo);
|
||||
|
||||
cblas_scopy((int)countToDo, left_ptr, 1, outBuffer + 0, 2);
|
||||
cblas_scopy((int)countToDo, right_ptr, 1, outBuffer + 1, 2);
|
||||
|
||||
inBuffer += countToDo * channelCount;
|
||||
outBuffer += countToDo * 2;
|
||||
|
||||
count -= countToDo;
|
||||
|
||||
outBuffer[0] = left;
|
||||
outBuffer[1] = right;
|
||||
outBuffer += 2;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reset {
|
||||
for(int i = 0; i < channelCount; ++i) {
|
||||
vDSP_vclr(prevInputs[i], 1, fftSize);
|
||||
vDSP_vclr(prevInputs[i], 1, paddedBufferSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22138.1" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22154" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22138.1"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22154"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
@ -35,7 +35,7 @@
|
|||
<binding destination="52" name="value" keyPath="values.readCueSheetsInFolders" id="328"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="261">
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="261">
|
||||
<rect key="frame" x="18" y="127" width="180" height="35"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="When opening file with ⇧ or ⌃⌘ held:" id="262">
|
||||
|
@ -44,7 +44,7 @@
|
|||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="259">
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="259">
|
||||
<rect key="frame" x="18" y="168" width="180" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="When opening files:" id="260">
|
||||
|
@ -145,7 +145,7 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="640" height="163"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="24">
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="24">
|
||||
<rect key="frame" x="34" y="134" width="145" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Play:" id="198">
|
||||
|
@ -158,7 +158,7 @@
|
|||
<rect key="frame" x="185" y="133" width="163" height="19"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="25">
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="25">
|
||||
<rect key="frame" x="34" y="103" width="145" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Previous:" id="199">
|
||||
|
@ -171,7 +171,7 @@
|
|||
<rect key="frame" x="185" y="102" width="163" height="19"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="26">
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="26">
|
||||
<rect key="frame" x="4" y="73" width="175" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Next:" id="200">
|
||||
|
@ -184,7 +184,7 @@
|
|||
<rect key="frame" x="185" y="72" width="163" height="19"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Gp4-rA-1UF">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Gp4-rA-1UF">
|
||||
<rect key="frame" x="4" y="44" width="175" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Fade in/out:" id="D5K-pO-8Sj">
|
||||
|
@ -197,7 +197,7 @@
|
|||
<rect key="frame" x="185" y="43" width="163" height="19"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eid-M4-6Cs">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eid-M4-6Cs">
|
||||
<rect key="frame" x="4" y="14" width="175" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Copy now playing:" id="SMd-GA-jrH">
|
||||
|
@ -271,7 +271,7 @@
|
|||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rG5-80-FId">
|
||||
<rect key="frame" x="18" y="80" width="602" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Enable HRTF filter (Not needed with AirPods or Beats)" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="NGx-0c-WVR">
|
||||
<buttonCell key="cell" type="check" title="Enable HRTF filter" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="NGx-0c-WVR">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
|
@ -279,7 +279,7 @@
|
|||
<binding destination="52" name="value" keyPath="values.enableHrtf" id="BD0-cP-SfB"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="65">
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="65">
|
||||
<rect key="frame" x="6" y="53" width="134" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Output Device: " id="211">
|
||||
|
@ -309,7 +309,7 @@
|
|||
<binding destination="59" name="selectedIndex" keyPath="selectionIndex" previousBinding="71" id="72"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zkP-2E-1Kc">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zkP-2E-1Kc">
|
||||
<rect key="frame" x="17" y="20" width="123" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Volume Level:" id="wK4-EF-8Wa">
|
||||
|
@ -407,7 +407,7 @@
|
|||
<binding destination="52" name="value" keyPath="values.crashlyticsConsented" id="GQu-a0-JJs"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="crf-C9-9YF">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="crf-C9-9YF">
|
||||
<rect key="frame" x="20" y="142" width="170" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Folder access paths:" id="wWm-AD-cD4">
|
||||
|
@ -446,7 +446,7 @@
|
|||
<rect key="frame" x="8" y="0.0" width="443" height="24"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7l9-R2-FVF">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7l9-R2-FVF">
|
||||
<rect key="frame" x="0.0" y="4" width="443" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="7un-em-D8r">
|
||||
|
@ -481,7 +481,7 @@
|
|||
<rect key="frame" x="468" y="0.0" width="100" height="24"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0TJ-dK-Rfk">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0TJ-dK-Rfk">
|
||||
<rect key="frame" x="0.0" y="4" width="100" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="LwT-Qb-47r">
|
||||
|
@ -628,7 +628,7 @@
|
|||
</binding>
|
||||
</connections>
|
||||
</colorWell>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1Xc-Cr-icC">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1Xc-Cr-icC">
|
||||
<rect key="frame" x="70" y="51" width="552" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Spectrum bars" id="Bll-IJ-lje">
|
||||
|
@ -649,7 +649,7 @@
|
|||
</binding>
|
||||
</connections>
|
||||
</colorWell>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ahQ-bv-j9g">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ahQ-bv-j9g">
|
||||
<rect key="frame" x="70" y="23" width="552" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Spectrum peaks" id="CQI-YZ-B3V">
|
||||
|
@ -676,7 +676,7 @@
|
|||
<action selector="setSoundFont:" target="i5B-ga-Atm" id="b2t-MX-dua"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FRC-Dh-BS2" userLabel="Text Field - Selected:">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FRC-Dh-BS2" userLabel="Text Field - Selected:">
|
||||
<rect key="frame" x="296" y="211" width="96" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Selected:" id="KJz-qS-IcO" userLabel="Text Field Cell - Selected">
|
||||
|
@ -685,7 +685,7 @@
|
|||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cZr-2d-6cv">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cZr-2d-6cv">
|
||||
<rect key="frame" x="394" y="211" width="228" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Label" id="ECB-P0-pve">
|
||||
|
@ -702,7 +702,7 @@
|
|||
</connections>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4uG-vW-B64">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4uG-vW-B64">
|
||||
<rect key="frame" x="18" y="182" width="274" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="MIDI Plugin:" id="n5F-dq-NZh">
|
||||
|
@ -732,7 +732,7 @@
|
|||
<binding destination="52" name="selectedObject" keyPath="values.midiPlugin" previousBinding="6JE-ba-47Z" id="ePY-TV-ngD"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="G86-18-hiK">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="G86-18-hiK">
|
||||
<rect key="frame" x="18" y="151" width="274" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Resampling Quality:" id="eX0-PC-iVo">
|
||||
|
@ -762,7 +762,7 @@
|
|||
<binding destination="52" name="selectedObject" keyPath="values.resampling" previousBinding="KxI-52-0UK" id="wsy-tb-NFy"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="K5c-km-7Qa">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="K5c-km-7Qa">
|
||||
<rect key="frame" x="20" y="120" width="272" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="MIDI Flavor:" id="FQF-vJ-hBx">
|
||||
|
@ -792,7 +792,7 @@
|
|||
<binding destination="52" name="selectedObject" keyPath="values.midi.flavor" previousBinding="Rvq-46-YeR" id="zC1-3J-frL"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ygc-nv-ZkO">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ygc-nv-ZkO">
|
||||
<rect key="frame" x="18" y="94" width="274" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Default play time:" id="AQZ-ku-F8u">
|
||||
|
@ -801,7 +801,7 @@
|
|||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="l3L-N5-gU1">
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="l3L-N5-gU1">
|
||||
<rect key="frame" x="298" y="91" width="91" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" alignment="center" drawsBackground="YES" id="Isi-54-78h">
|
||||
|
@ -817,7 +817,7 @@
|
|||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="JmH-HM-zwz">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="JmH-HM-zwz">
|
||||
<rect key="frame" x="394" y="94" width="228" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="hh:mm:ss.ms" id="klv-Wh-0ur">
|
||||
|
@ -826,7 +826,7 @@
|
|||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qhe-ea-0bx">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qhe-ea-0bx">
|
||||
<rect key="frame" x="18" y="68" width="274" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Default fade time:" id="UdW-qd-A0x">
|
||||
|
@ -835,7 +835,7 @@
|
|||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HDu-ff-N3s">
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HDu-ff-N3s">
|
||||
<rect key="frame" x="298" y="65" width="91" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" alignment="center" drawsBackground="YES" id="9Hu-FG-spW">
|
||||
|
@ -851,7 +851,7 @@
|
|||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eyL-LI-NzO">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eyL-LI-NzO">
|
||||
<rect key="frame" x="394" y="68" width="228" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="hh:mm:ss.ms" id="zaI-0m-tQf">
|
||||
|
@ -860,7 +860,7 @@
|
|||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4PD-ys-Cfu">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4PD-ys-Cfu">
|
||||
<rect key="frame" x="18" y="42" width="274" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Default loop count:" id="Fgm-Vs-tgU">
|
||||
|
@ -869,7 +869,7 @@
|
|||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FX5-Lt-csQ">
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FX5-Lt-csQ">
|
||||
<rect key="frame" x="298" y="39" width="91" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="center" drawsBackground="YES" id="v5P-kg-a0v">
|
||||
|
@ -882,7 +882,7 @@
|
|||
<binding destination="52" name="value" keyPath="values.synthDefaultLoopCount" id="h30-gW-yrc"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8jM-zP-FSb">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8jM-zP-FSb">
|
||||
<rect key="frame" x="394" y="12" width="201" height="46"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" alignment="right" title="(will be preferred if possible)" id="POG-ai-6D2">
|
||||
|
@ -891,7 +891,7 @@
|
|||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Rrf-kn-YnS">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Rrf-kn-YnS">
|
||||
<rect key="frame" x="18" y="15" width="274" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Sample rate:" id="A9I-fr-vHp">
|
||||
|
@ -900,7 +900,7 @@
|
|||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CiQ-nY-YXA">
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CiQ-nY-YXA">
|
||||
<rect key="frame" x="298" y="12" width="91" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="right" drawsBackground="YES" id="h3A-Br-Gyc">
|
||||
|
@ -913,7 +913,7 @@
|
|||
<binding destination="52" name="value" keyPath="values.synthSampleRate" id="C52-5h-iFA"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="esA-Kb-zTw">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="esA-Kb-zTw">
|
||||
<rect key="frame" x="394" y="15" width="228" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Hz" id="0Am-5Y-EKq">
|
||||
|
|
|
@ -230,8 +230,8 @@
|
|||
/* Class = "NSButtonCell"; title = "Use 3D rendered spectrum"; ObjectID = "NMg-TO-amV"; */
|
||||
"NMg-TO-amV.title" = "Use 3D rendered spectrum";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Enable HRTF filter (Not needed with AirPods or Beats)"; ObjectID = "NGx-0c-WVR"; */
|
||||
"NGx-0c-WVR.title" = "Enable HRTF filter (Not needed with AirPods or Beats)";
|
||||
/* Class = "NSButtonCell"; title = "Enable HRTF filter"; ObjectID = "NGx-0c-WVR"; */
|
||||
"NGx-0c-WVR.title" = "Enable HRTF filter";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Enable FreeSurround stereo to surround upmixing"; ObjectID = "F0i-UK-6Nu"; */
|
||||
"F0i-UK-6Nu.title" = "Enable FreeSurround stereo to surround upmixing";
|
||||
|
|
|
@ -226,8 +226,8 @@
|
|||
/* Class = "NSButtonCell"; title = "Use 3D rendered spectrum"; ObjectID = "NMg-TO-amV"; */
|
||||
"NMg-TO-amV.title" = "Usar analizador en tres dimensiones";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Enable HRTF filter (Not needed with AirPods or Beats)"; ObjectID = "NGx-0c-WVR"; */
|
||||
"NGx-0c-WVR.title" = "Activar filtro HRTF (no es necesario con AirPods o Beats)";
|
||||
/* Class = "NSButtonCell"; title = "Enable HRTF filter"; ObjectID = "NGx-0c-WVR"; */
|
||||
"NGx-0c-WVR.title" = "Activar filtro HRTF";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Automatically check for updates on startup"; ObjectID = "207"; */
|
||||
"207.title" = "Buscar actualizaciones al abrir";
|
||||
|
|
|
@ -191,8 +191,8 @@
|
|||
/* Class = "NSButtonCell"; title = "Use 3D rendered spectrum"; ObjectID = "NMg-TO-amV"; */
|
||||
"NMg-TO-amV.title" = "Использовать 3D-рендеринг спектра";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Enable HRTF filter (Not needed with AirPods or Beats)"; ObjectID = "NGx-0c-WVR"; */
|
||||
"NGx-0c-WVR.title" = "Включить фильтр HRTF (не требуется с AirPods или Beats)";
|
||||
/* Class = "NSButtonCell"; title = "Enable HRTF filter"; ObjectID = "NGx-0c-WVR"; */
|
||||
"NGx-0c-WVR.title" = "Включить фильтр HRTF";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Enable FreeSurround stereo to surround upmixing"; ObjectID = "F0i-UK-6Nu"; */
|
||||
"F0i-UK-6Nu.title" = "Включить FreeSurround апмикс стерео в объемный звук";
|
||||
|
|
|
@ -128,8 +128,8 @@
|
|||
/* Class = "NSTextFieldCell"; title = "Table View Cell"; ObjectID = "LwT-Qb-47r"; */
|
||||
"LwT-Qb-47r.title" = "Tablo Görünümü Hücresi";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Enable HRTF filter (Not needed with AirPods or Beats)"; ObjectID = "NGx-0c-WVR"; */
|
||||
"NGx-0c-WVR.title" = "HRTF filtresini etkinleştir (Airpods veya Beats ile gerekli değildir)";
|
||||
/* Class = "NSButtonCell"; title = "Enable HRTF filter"; ObjectID = "NGx-0c-WVR"; */
|
||||
"NGx-0c-WVR.title" = "HRTF filtresini etkinleştir";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Use 3D rendered spectrum"; ObjectID = "NMg-TO-amV"; */
|
||||
"NMg-TO-amV.title" = "3D işlenmiş spektrum kullanın";
|
||||
|
|
Loading…
Reference in a new issue