diff --git a/Audio/Chain/BufferChain.h b/Audio/Chain/BufferChain.h index dbfeef689..a9ea34b42 100644 --- a/Audio/Chain/BufferChain.h +++ b/Audio/Chain/BufferChain.h @@ -11,12 +11,14 @@ #import "AudioPlayer.h" #import "ConverterNode.h" #import "DSPRubberbandNode.h" +#import "DSPFSurroundNode.h" #import "InputNode.h" @interface BufferChain : NSObject { InputNode *inputNode; ConverterNode *converterNode; DSPRubberbandNode *rubberbandNode; + DSPFSurroundNode *fsurroundNode; NSURL *streamURL; id userInfo; @@ -75,6 +77,8 @@ - (DSPRubberbandNode *)rubberband; +- (DSPFSurroundNode *)fsurround; + - (double)secondsBuffered; - (void)sustainHDCD; diff --git a/Audio/Chain/BufferChain.m b/Audio/Chain/BufferChain.m index 2e5a7b452..1ba3ad8eb 100644 --- a/Audio/Chain/BufferChain.m +++ b/Audio/Chain/BufferChain.m @@ -27,6 +27,7 @@ converterNode = nil; rubberbandNode = nil; + fsurroundNode = nil; } return self; @@ -39,8 +40,9 @@ inputNode = [[InputNode alloc] initWithController:self previous:nil]; converterNode = [[ConverterNode alloc] initWithController:self previous:inputNode]; rubberbandNode = [[DSPRubberbandNode alloc] initWithController:self previous:converterNode latency:0.03]; + fsurroundNode = [[DSPFSurroundNode alloc] initWithController:self previous:rubberbandNode latency:0.03]; - finalNode = rubberbandNode; + finalNode = fsurroundNode; } - (BOOL)open:(NSURL *)url withOutputFormat:(AudioStreamBasicDescription)outputFormat withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi { @@ -150,6 +152,7 @@ [inputNode launchThread]; [converterNode launchThread]; [rubberbandNode launchThread]; + [fsurroundNode launchThread]; } - (void)setUserInfo:(id)i { @@ -218,6 +221,7 @@ [inputNode setShouldContinue:s]; [converterNode setShouldContinue:s]; [rubberbandNode setShouldContinue:s]; + [fsurroundNode setShouldContinue:s]; } - (BOOL)isRunning { @@ -240,6 +244,10 @@ return rubberbandNode; } +- (DSPFSurroundNode *)fsurround { + return fsurroundNode; +} + - (AudioStreamBasicDescription)inputFormat { return [inputNode nodeFormat]; } diff --git a/Audio/Chain/DSP/DSPFSurroundNode.h b/Audio/Chain/DSP/DSPFSurroundNode.h new file mode 100644 index 000000000..dc9a19c10 --- /dev/null +++ b/Audio/Chain/DSP/DSPFSurroundNode.h @@ -0,0 +1,28 @@ +// +// DSPFSurroundNode.h +// CogAudio +// +// Created by Christopher Snowhill on 2/11/25. +// + +#ifndef DSPFSurroundNode_h +#define DSPFSurroundNode_h + +#import "DSPNode.h" + +@interface DSPFSurroundNode : DSPNode { +} + +- (id _Nullable)initWithController:(id _Nonnull)c previous:(id _Nullable)p latency:(double)latency; + +- (BOOL)setup; +- (void)cleanUp; + +- (void)resetBuffer; + +- (void)process; +- (AudioChunk * _Nullable)convert; + +@end + +#endif /* DSPFSurroundNode_h */ diff --git a/Audio/Chain/DSP/DSPFSurroundNode.m b/Audio/Chain/DSP/DSPFSurroundNode.m new file mode 100644 index 000000000..e48ec6c2b --- /dev/null +++ b/Audio/Chain/DSP/DSPFSurroundNode.m @@ -0,0 +1,264 @@ +// +// DSPFSurroundNode.m +// CogAudio Framework +// +// Created by Christopher Snowhill on 2/11/25. +// + +#import + +#import + +#import "DSPFSurroundNode.h" + +#import "FSurroundFilter.h" + +#define OCTAVES 5 + +static void * kDSPFSurroundNodeContext = &kDSPFSurroundNodeContext; + +@implementation DSPFSurroundNode { + BOOL enableFSurround; + BOOL FSurroundDelayRemoved; + BOOL resetStreamFormat; + FSurroundFilter *fsurround; + + BOOL stopping, paused; + BOOL processEntered; + + BOOL observersapplied; + + AudioStreamBasicDescription lastInputFormat; + AudioStreamBasicDescription inputFormat; + AudioStreamBasicDescription outputFormat; + + uint32_t lastInputChannelConfig, inputChannelConfig; + uint32_t outputChannelConfig; + + float inBuffer[4096 * 2]; + float outBuffer[8192 * 6]; +} + +- (id _Nullable)initWithController:(id _Nonnull)c previous:(id _Nullable)p latency:(double)latency { + self = [super initWithController:c previous:p latency:latency]; + if(self) { + NSUserDefaults *defaults = [[NSUserDefaultsController sharedUserDefaultsController] defaults]; + enableFSurround = [defaults boolForKey:@"enableFSurround"]; + + [self addObservers]; + } + return self; +} + +- (void)dealloc { + [self cleanUp]; + [self removeObservers]; +} + +- (void)addObservers { + [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.enableFSurround" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kDSPFSurroundNodeContext]; + + observersapplied = YES; +} + +- (void)removeObservers { + if(observersapplied) { + [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.enableFSurround" context:kDSPFSurroundNodeContext]; + observersapplied = NO; + } +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if(context != kDSPFSurroundNodeContext) { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + return; + } + + if([keyPath isEqualToString:@"values.enableFSurround"]) { + NSUserDefaults *defaults = [[NSUserDefaultsController sharedUserDefaultsController] defaults]; + enableFSurround = [defaults boolForKey:@"enableFSurround"]; + } +} + +- (BOOL)fullInit { + if(enableFSurround && inputFormat.mChannelsPerFrame == 2) { + fsurround = [[FSurroundFilter alloc] initWithSampleRate:inputFormat.mSampleRate]; + if(!fsurround) { + return NO; + } + outputFormat = inputFormat; + outputFormat.mChannelsPerFrame = [fsurround channelCount]; + outputFormat.mBytesPerFrame = sizeof(float) * outputFormat.mChannelsPerFrame; + outputFormat.mBytesPerPacket = outputFormat.mBytesPerFrame * outputFormat.mFramesPerPacket; + outputChannelConfig = [fsurround channelConfig]; + + FSurroundDelayRemoved = NO; + resetStreamFormat = YES; + } else { + fsurround = nil; + } + + return YES; +} + +- (void)fullShutdown { + fsurround = nil; +} + +- (BOOL)setup { + if(stopping) + return NO; + [self fullShutdown]; + return [self fullInit]; +} + +- (void)cleanUp { + stopping = YES; + while(processEntered) { + usleep(1000); + } + [self fullShutdown]; +} + +- (void)resetBuffer { + paused = YES; + while(processEntered) { + usleep(500); + } + [super resetBuffer]; + [self fullShutdown]; + paused = NO; +} + +- (void)process { + while([self shouldContinue] == YES) { + if(paused) { + usleep(500); + continue; + } + @autoreleasepool { + AudioChunk *chunk = nil; + chunk = [self convert]; + if(!chunk) { + if([self endOfStream] == YES) { + break; + } + if(paused) { + continue; + } + } else { + [self writeChunk:chunk]; + chunk = nil; + } + if(!enableFSurround && fsurround) { + [self fullShutdown]; + } + } + } +} + +- (AudioChunk *)convert { + if(stopping) + return nil; + + processEntered = YES; + + if(stopping || [self endOfStream] == YES || [self shouldContinue] == NO) { + processEntered = NO; + return nil; + } + + if(![self peekFormat:&inputFormat channelConfig:&inputChannelConfig]) { + processEntered = NO; + return nil; + } + + if((enableFSurround && !fsurround) || + memcmp(&inputFormat, &lastInputFormat, sizeof(inputFormat)) != 0 || + inputChannelConfig != lastInputChannelConfig) { + lastInputFormat = inputFormat; + lastInputChannelConfig = inputChannelConfig; + [self fullShutdown]; + if(![self setup]) { + processEntered = NO; + return nil; + } + } + + if(!fsurround) { + processEntered = NO; + return [self readChunk:4096]; + } + + size_t totalRequestedSamples = resetStreamFormat ? 2048 : 4096; + + size_t totalFrameCount = 0; + AudioChunk *chunk; + + float *samplePtr = resetStreamFormat ? &inBuffer[2048 * 2] : &inBuffer[0]; + + while(!stopping && totalFrameCount < totalRequestedSamples) { + chunk = [self readChunkAsFloat32:totalRequestedSamples - totalFrameCount]; + if(!chunk) { + break; + } + + size_t frameCount = [chunk frameCount]; + NSData *sampleData = [chunk removeSamples:frameCount]; + + cblas_scopy((int)frameCount * 2, [sampleData bytes], 1, &samplePtr[totalFrameCount * 2], 1); + + totalFrameCount += frameCount; + } + + if(!totalFrameCount) { + processEntered = NO; + return nil; + } + + if(resetStreamFormat) { + bzero(&inBuffer[0], 2048 * 2 * sizeof(float)); + totalFrameCount += 2048; + resetStreamFormat = NO; + } + + size_t countToProcess = totalFrameCount; + size_t samplesRendered; + if(countToProcess < 4096) { + bzero(&inBuffer[countToProcess * 2], (4096 - countToProcess) * 2 * sizeof(float)); + countToProcess = 4096; + } + + [fsurround process:&inBuffer[0] output:&outBuffer[4096 * 6] count:(int)countToProcess]; + samplePtr = &outBuffer[4096 * 6]; + samplesRendered = totalFrameCount; + + if(totalFrameCount < 4096) { + bzero(&outBuffer[4096 * 6], 4096 * 2 * sizeof(float)); + [fsurround process:&outBuffer[4096 * 6] output:&outBuffer[4096 * 6] count:4096]; + samplesRendered += 2048; + } + + if(!FSurroundDelayRemoved) { + FSurroundDelayRemoved = YES; + if(samplesRendered > 2048) { + samplePtr += 2048 * 6; + samplesRendered -= 2048; + } + } + + AudioChunk *outputChunk = nil; + if(samplesRendered) { + outputChunk = [[AudioChunk alloc] init]; + [outputChunk setFormat:outputFormat]; + if(outputChannelConfig) { + [outputChunk setChannelConfig:outputChannelConfig]; + } + [outputChunk assignSamples:samplePtr frameCount:samplesRendered]; + } + + processEntered = NO; + return outputChunk; +} + +@end diff --git a/Audio/Output/FSurroundFilter.h b/Audio/Chain/DSP/FSurroundFilter.h similarity index 100% rename from Audio/Output/FSurroundFilter.h rename to Audio/Chain/DSP/FSurroundFilter.h diff --git a/Audio/Output/FSurroundFilter.mm b/Audio/Chain/DSP/FSurroundFilter.mm similarity index 100% rename from Audio/Output/FSurroundFilter.mm rename to Audio/Chain/DSP/FSurroundFilter.mm diff --git a/Audio/Chain/InputNode.m b/Audio/Chain/InputNode.m index 0cf96dcbe..7e936a5f4 100644 --- a/Audio/Chain/InputNode.m +++ b/Audio/Chain/InputNode.m @@ -162,6 +162,7 @@ static void *kInputNodeContext = &kInputNodeContext; BufferChain *bufferChain = [[controller controller] bufferChain]; ConverterNode *converter = [bufferChain converter]; DSPRubberbandNode *rubberband = [bufferChain rubberband]; + DSPFSurroundNode *fsurround = [bufferChain fsurround]; DLog(@"SEEKING! Resetting Buffer"); // This resets the converter's buffer @@ -169,6 +170,7 @@ static void *kInputNodeContext = &kInputNodeContext; [converter resetBuffer]; [converter inputFormatDidChange:[bufferChain inputFormat] inputConfig:[bufferChain inputConfig]]; [rubberband resetBuffer]; + [fsurround resetBuffer]; DLog(@"Reset buffer!"); diff --git a/Audio/CogAudio.xcodeproj/project.pbxproj b/Audio/CogAudio.xcodeproj/project.pbxproj index 6ae89f7d0..e8fffdf80 100644 --- a/Audio/CogAudio.xcodeproj/project.pbxproj +++ b/Audio/CogAudio.xcodeproj/project.pbxproj @@ -53,8 +53,6 @@ 834A41AA287A90AB00EB9D9B /* freesurround_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 834A41A6287A90AB00EB9D9B /* freesurround_decoder.cpp */; }; 834A41AB287A90AB00EB9D9B /* channelmaps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 834A41A7287A90AB00EB9D9B /* channelmaps.cpp */; }; 834A41AC287A90AB00EB9D9B /* channelmaps.h in Headers */ = {isa = PBXBuildFile; fileRef = 834A41A8287A90AB00EB9D9B /* channelmaps.h */; }; - 834A41AF287ABD6F00EB9D9B /* FSurroundFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 834A41AD287ABD6F00EB9D9B /* FSurroundFilter.h */; }; - 834A41B0287ABD6F00EB9D9B /* FSurroundFilter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 834A41AE287ABD6F00EB9D9B /* FSurroundFilter.mm */; }; 834FD4EB27AF8F380063BC83 /* AudioChunk.h in Headers */ = {isa = PBXBuildFile; fileRef = 834FD4EA27AF8F380063BC83 /* AudioChunk.h */; }; 834FD4ED27AF91220063BC83 /* AudioChunk.m in Sources */ = {isa = PBXBuildFile; fileRef = 834FD4EC27AF91220063BC83 /* AudioChunk.m */; }; 834FD4F027AF93680063BC83 /* ChunkList.h in Headers */ = {isa = PBXBuildFile; fileRef = 834FD4EE27AF93680063BC83 /* ChunkList.h */; }; @@ -96,6 +94,10 @@ 839E56F7287974A100DFB5F4 /* SandboxBroker.h in Headers */ = {isa = PBXBuildFile; fileRef = 839E56F6287974A100DFB5F4 /* SandboxBroker.h */; }; 83A3496A2D5C3F430096D530 /* DSPRubberbandNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A349682D5C3F430096D530 /* DSPRubberbandNode.m */; }; 83A3496B2D5C3F430096D530 /* DSPRubberbandNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A349672D5C3F430096D530 /* DSPRubberbandNode.h */; }; + 83A3496D2D5C40490096D530 /* DSPFSurroundNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A3496C2D5C40490096D530 /* DSPFSurroundNode.h */; }; + 83A3496F2D5C405E0096D530 /* DSPFSurroundNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A3496E2D5C405E0096D530 /* DSPFSurroundNode.m */; }; + 83A349722D5C41810096D530 /* FSurroundFilter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83A349712D5C41810096D530 /* FSurroundFilter.mm */; }; + 83A349732D5C41810096D530 /* FSurroundFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A349702D5C41810096D530 /* FSurroundFilter.h */; }; 83B74281289E027F005AAC28 /* CogAudio-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = 83B74280289E027F005AAC28 /* CogAudio-Bridging-Header.h */; }; 83FFED512D5B08BC0044CCAF /* DSPNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 83FFED502D5B08BC0044CCAF /* DSPNode.h */; }; 83FFED532D5B09320044CCAF /* DSPNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 83FFED522D5B09320044CCAF /* DSPNode.m */; }; @@ -171,8 +173,6 @@ 834A41A6287A90AB00EB9D9B /* freesurround_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = freesurround_decoder.cpp; sourceTree = ""; }; 834A41A7287A90AB00EB9D9B /* channelmaps.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = channelmaps.cpp; sourceTree = ""; }; 834A41A8287A90AB00EB9D9B /* channelmaps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = channelmaps.h; sourceTree = ""; }; - 834A41AD287ABD6F00EB9D9B /* FSurroundFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSurroundFilter.h; sourceTree = ""; }; - 834A41AE287ABD6F00EB9D9B /* FSurroundFilter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSurroundFilter.mm; sourceTree = ""; }; 834FD4EA27AF8F380063BC83 /* AudioChunk.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AudioChunk.h; sourceTree = ""; }; 834FD4EC27AF91220063BC83 /* AudioChunk.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AudioChunk.m; sourceTree = ""; }; 834FD4EE27AF93680063BC83 /* ChunkList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChunkList.h; sourceTree = ""; }; @@ -214,6 +214,10 @@ 839E56F6287974A100DFB5F4 /* SandboxBroker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SandboxBroker.h; path = ../Utils/SandboxBroker.h; sourceTree = ""; }; 83A349672D5C3F430096D530 /* DSPRubberbandNode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DSPRubberbandNode.h; sourceTree = ""; }; 83A349682D5C3F430096D530 /* DSPRubberbandNode.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DSPRubberbandNode.m; sourceTree = ""; }; + 83A3496C2D5C40490096D530 /* DSPFSurroundNode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DSPFSurroundNode.h; sourceTree = ""; }; + 83A3496E2D5C405E0096D530 /* DSPFSurroundNode.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DSPFSurroundNode.m; sourceTree = ""; }; + 83A349702D5C41810096D530 /* FSurroundFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSurroundFilter.h; sourceTree = ""; }; + 83A349712D5C41810096D530 /* FSurroundFilter.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FSurroundFilter.mm; sourceTree = ""; }; 83B74280289E027F005AAC28 /* CogAudio-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CogAudio-Bridging-Header.h"; sourceTree = ""; }; 83FFED502D5B08BC0044CCAF /* DSPNode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DSPNode.h; sourceTree = ""; }; 83FFED522D5B09320044CCAF /* DSPNode.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DSPNode.m; sourceTree = ""; }; @@ -381,8 +385,6 @@ children = ( 835DD2662ACAF1D90057E319 /* OutputCoreAudio.h */, 835DD2652ACAF1D90057E319 /* OutputCoreAudio.m */, - 834A41AD287ABD6F00EB9D9B /* FSurroundFilter.h */, - 834A41AE287ABD6F00EB9D9B /* FSurroundFilter.mm */, 839E56EB2879515D00DFB5F4 /* HeadphoneFilter.h */, 839E56EC2879515D00DFB5F4 /* HeadphoneFilter.mm */, ); @@ -524,8 +526,12 @@ 83A349692D5C3F430096D530 /* DSP */ = { isa = PBXGroup; children = ( + 83A349702D5C41810096D530 /* FSurroundFilter.h */, + 83A349712D5C41810096D530 /* FSurroundFilter.mm */, 83A349672D5C3F430096D530 /* DSPRubberbandNode.h */, 83A349682D5C3F430096D530 /* DSPRubberbandNode.m */, + 83A3496C2D5C40490096D530 /* DSPFSurroundNode.h */, + 83A3496E2D5C405E0096D530 /* DSPFSurroundNode.m */, ); path = DSP; sourceTree = ""; @@ -539,6 +545,7 @@ files = ( 839E56E82879450300DFB5F4 /* IHrtfData.h in Headers */, 17D21CA10B8BE4BA00D1EBDE /* BufferChain.h in Headers */, + 83A3496D2D5C40490096D530 /* DSPFSurroundNode.h in Headers */, 831A50142865A7FD0049CFE4 /* rsstate.hpp in Headers */, 834A41AC287A90AB00EB9D9B /* channelmaps.h in Headers */, 17D21CA50B8BE4BA00D1EBDE /* InputNode.h in Headers */, @@ -565,7 +572,6 @@ 17F94DDD0B8D101100A34E87 /* Plugin.h in Headers */, 8328995727CB51B700D7F028 /* SHA256Digest.h in Headers */, 834FD4EB27AF8F380063BC83 /* AudioChunk.h in Headers */, - 834A41AF287ABD6F00EB9D9B /* FSurroundFilter.h in Headers */, 83A3496B2D5C3F430096D530 /* DSPRubberbandNode.h in Headers */, 17A2D3C50B8D1D37000778C4 /* AudioDecoder.h in Headers */, 8347C7412796C58800FA8A7D /* NSFileHandle+CreateFile.h in Headers */, @@ -578,6 +584,7 @@ 17ADB13C0B97926D00257CA2 /* AudioSource.h in Headers */, 835C88B1279811A500E28EAE /* hdcd_decode2.h in Headers */, 8EC1225F0B993BD500C5B3AD /* ConverterNode.h in Headers */, + 83A349732D5C41810096D530 /* FSurroundFilter.h in Headers */, 8384912718080FF100E7332D /* Logging.h in Headers */, 8377C64E27B8C54400E8BC0F /* fft.h in Headers */, 835FAC5E27BCA14D00BA8562 /* BadSampleCleaner.h in Headers */, @@ -676,6 +683,7 @@ 17D21CF40B8BE5EF00D1EBDE /* CogSemaphore.m in Sources */, 839B83FA286D91ED00F529EE /* VisualizationController.swift in Sources */, 8347C7422796C58800FA8A7D /* NSFileHandle+CreateFile.m in Sources */, + 83A3496F2D5C405E0096D530 /* DSPFSurroundNode.m in Sources */, 17D21DC80B8BE79700D1EBDE /* CoreAudioUtils.m in Sources */, 8328995327CB511000D7F028 /* RedundantPlaylistDataStore.m in Sources */, 8377C64C27B8C51500E8BC0F /* fft_accelerate.c in Sources */, @@ -689,10 +697,10 @@ 17B619310B909BC300BC003F /* AudioPropertiesReader.m in Sources */, 17ADB13D0B97926D00257CA2 /* AudioSource.m in Sources */, 834FD4F127AF93680063BC83 /* ChunkList.m in Sources */, - 834A41B0287ABD6F00EB9D9B /* FSurroundFilter.mm in Sources */, 83FFED532D5B09320044CCAF /* DSPNode.m in Sources */, 8EC122600B993BD500C5B3AD /* ConverterNode.m in Sources */, 835DD2672ACAF1D90057E319 /* OutputCoreAudio.m in Sources */, + 83A349722D5C41810096D530 /* FSurroundFilter.mm in Sources */, 8E8D3D300CBAEE6E00135C1B /* AudioContainer.m in Sources */, B0575F300D687A4000411D77 /* Helper.m in Sources */, 835DD2742ACAF5AD0057E319 /* lpc.c in Sources */, diff --git a/Audio/Output/OutputCoreAudio.h b/Audio/Output/OutputCoreAudio.h index 0f968d6c5..67051628c 100644 --- a/Audio/Output/OutputCoreAudio.h +++ b/Audio/Output/OutputCoreAudio.h @@ -37,8 +37,6 @@ using std::atomic_long; @class OutputNode; -@class FSurroundFilter; - @class AudioChunk; @interface OutputCoreAudio : NSObject { @@ -119,10 +117,7 @@ using std::atomic_long; BOOL enableHrtf; HeadphoneFilter *hrtf; - BOOL enableFSurround; - BOOL FSurroundDelayRemoved; int inputBufferLastTime; - FSurroundFilter *fsurround; int inputRemain; @@ -137,7 +132,6 @@ using std::atomic_long; float *samplePtr; float tempBuffer[512 * 32]; float inputBuffer[4096 * 32]; // 4096 samples times maximum supported channel count - float fsurroundBuffer[8192 * 6]; float hrtfBuffer[4096 * 2]; float eqBuffer[4096 * 32]; float eqOutBuffer[4096 * 32]; diff --git a/Audio/Output/OutputCoreAudio.m b/Audio/Output/OutputCoreAudio.m index 47be2a4b9..dd144fe7f 100644 --- a/Audio/Output/OutputCoreAudio.m +++ b/Audio/Output/OutputCoreAudio.m @@ -21,10 +21,6 @@ #import "rsstate.h" -#import "FSurroundFilter.h" - -#define OCTAVES 5 - extern void scale_by_volume(float *buffer, size_t count, float volume); static NSString *CogPlaybackDidBeginNotificiation = @"CogPlaybackDidBeginNotificiation"; @@ -152,10 +148,6 @@ static OSStatus eqRenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioA AudioStreamBasicDescription dmFormat; dmFormat = format; [outputLock lock]; - if(fsurround) { - dmChannels = [fsurround channelCount]; - dmConfig = [fsurround channelConfig]; - } if(hrtf) { dmChannels = 2; dmConfig = AudioChannelFrontLeft | AudioChannelFrontRight; @@ -397,10 +389,6 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons enableHeadTracking = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"enableHeadTracking"]; if(streamFormatStarted) resetStreamFormat = YES; - } else if([keyPath isEqualToString:@"values.enableFSurround"]) { - enableFSurround = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"enableFSurround"]; - if(streamFormatStarted) - resetStreamFormat = YES; } else if([keyPath isEqualToString:@"values.tempo"]) { tempo = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] doubleForKey:@"tempo"]; } @@ -775,19 +763,6 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons uint32_t channels = realStreamFormat.mChannelsPerFrame; uint32_t channelConfig = realStreamChannelConfig; - if(enableFSurround && channels == 2 && channelConfig == AudioConfigStereo) { - [outputLock lock]; - fsurround = [[FSurroundFilter alloc] initWithSampleRate:realStreamFormat.mSampleRate]; - [outputLock unlock]; - channels = [fsurround channelCount]; - channelConfig = [fsurround channelConfig]; - FSurroundDelayRemoved = NO; - } else { - [outputLock lock]; - fsurround = nil; - [outputLock unlock]; - } - if(enableHrtf) { NSURL *presetUrl = [[NSBundle mainBundle] URLForResource:@"SADIE_D02-96000" withExtension:@"mhr"]; @@ -956,31 +931,7 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons samplePtr = &inputBuffer[0]; - if(samplesRendered || fsurround) { - [outputLock lock]; - if(fsurround) { - int countToProcess = samplesRendered; - if(countToProcess < 4096) { - bzero(samplePtr + countToProcess * 2, (4096 - countToProcess) * 2 * sizeof(float)); - countToProcess = 4096; - } - [fsurround process:samplePtr output:&fsurroundBuffer[0] count:countToProcess]; - samplePtr = &fsurroundBuffer[0]; - if(resetStreamFormat || samplesRendered < 4096) { - bzero(&fsurroundBuffer[4096 * 6], 4096 * 2 * sizeof(float)); - [fsurround process:&fsurroundBuffer[4096 * 6] output:&fsurroundBuffer[4096 * 6] count:4096]; - samplesRendered += 2048; - } - if(!FSurroundDelayRemoved) { - FSurroundDelayRemoved = YES; - if(samplesRendered > 2048) { - samplePtr += 2048 * 6; - samplesRendered -= 2048; - } - } - } - [outputLock unlock]; - + if(samplesRendered) { [outputLock lock]; if(hrtf) { if(rotationMatrixUpdated) { @@ -1228,7 +1179,6 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.eqPreamp" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kOutputCoreAudioContext]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.enableHrtf" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kOutputCoreAudioContext]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.enableHeadTracking" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kOutputCoreAudioContext]; - [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.enableFSurround" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kOutputCoreAudioContext]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.tempo" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kOutputCoreAudioContext]; observersapplied = YES; @@ -1307,7 +1257,6 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.eqPreamp" context:kOutputCoreAudioContext]; [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.enableHrtf" context:kOutputCoreAudioContext]; [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.enableHeadTracking" context:kOutputCoreAudioContext]; - [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.enableFSurround" context:kOutputCoreAudioContext]; [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.tempo" context:kOutputCoreAudioContext]; observersapplied = NO; }